华为研发工程师编程题——明明的随机数

题目

[编程题]明明的随机数------来自牛客的华为研发工程师编程题,难度:🌟🌟🌟🌟

对于明明生成的 n 个 1 到 500 之间的随机整数,你需要帮助他完成以下任务:

∙删去重复的数字,即相同的数字只保留一个,把其余相同的数去掉;

∙然后再把这些数从小到大排序,按照排好的顺序输出。

你只需要输出最终的排序结果。

输入描述:

第一行输入一个整数 n (1≦n≦1000),代表明明生成的数字个数。

此后 n 行,第 i 行输入一个整数 ai (1≦ai ≦500),代表明明生成的随机整数。

输出描述:

输出若干行,每行输出一个整数,代表输入数据排序后的结果。第一行输出最小的数字。

示例1

输入

3

2

2

1

输出

1

2

解题
数组+插入排序

由于一开始没想起插入排序最好用链表来做,所以先写了数组版,思路如下:

  1. 读取输入的第一行,获得随机整数的总数
  2. 新建一个空数组nums,用来收集各输入数,存入nums的元素要遵循递增(即从小到大、不允许重复)的规则
  3. ACM输入的第一个整数存入nums第一位,后面的输入数逐个插入nums或被去重,直到处理完所有输入数。每次处理输入数都遵循以下处理流程:
    1. 处理流程第一步,读取下一个输入数作为新的待插入元素newNum,选取nums最后一个元素作为新的被比较元素compareNum,比较newNum与compareNum的大小
    2. newNum = compareNum,说明newNum是重复的数字,不必保留。回到处理流程第一步
    3. newNum > compareNum,则newNum大于compareNum及其左边的所有数,应把newNum插入nums中当前compareNum的后一位(nums.splice(compareNum的index + 1, 0, newNum))。回到处理流程第一步
    4. newNum < compareNum,且compareNum是nums中的第一位,说明newNum比nums中所有元素都要小,应把newNum插入nums的第一位(nums.unshift(newNum))。回到处理流程第一步
    5. newNum < compareNum,且compareNum不是nums中的第一位,说明newNum如果要插入的话,它的索引会比compareNum的索引更小,但还不知道具体是多少。应选取当前compareNum的前一位作为新的compareNum。回到处理流程第二步
  4. 处理完所有输入数后,nums就是一个包含所有输入数的数值且按递增顺序排列的数组了,现在遍历nums并打印出来。
typescript 复制代码
const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});
const inputLines = [];
rl.on("line", function (line: string) {
    inputLines.push(line.trim());
});
rl.on("close", function () {
    const numsLength = parseInt(inputLines[0]);
    // 数组nums是递增序列
    const nums = [];
    nums.push(parseInt(inputLines[1]));
    // 遍历输入数
    // 若新输入数按顺序插入了nums,或与已有元素重合了,则处理下一个输入数
    for (let newNumIdx = 2; newNumIdx <= numsLength; newNumIdx++) {
        const newNum = parseInt(inputLines[newNumIdx]);
        // 遍历nums
        let compareNumIdx = nums.length - 1;
        while (compareNumIdx >= 0) {
            const compareNum = nums[compareNumIdx];
            if (newNum === compareNum) {
            	// 退出nums遍历,去读取下一个输入数
                break;
            } else if (newNum > compareNum) {
            	// 插入新元素
                nums.splice(compareNumIdx + 1, 0, newNum);
                // 退出nums遍历,去读取下一个输入数
                break;
            } else {
                if (compareNumIdx === 0) {
                	// 在队首插入新元素
                    nums.unshift(newNum);
                    // 退出nums遍历,去读取下一个输入数
                	break;
                } else {
                	// 选取原被比较数的前一位作为新被比较数
                	compareNumIdx--;
                }
            }
        }
    }
    nums.forEach((num) => {
        console.log(num);
    });
});

遇到的问题:

  1. ACM输入问题一定要记得把输入字符串中的数字部份转为整数类型,否则把数字字符串当数字使用会出问题。比如1000>2是对的,但'1000'>'2'是错的,如果按从小到大排,程序会把'1000'排在'2'的前面。
  2. 流程比较复杂,主要是要熟悉插入排序的实现。
  3. 各循环的灵活度排名:while > for > forEach/map。
    如果想从数组的非开头元素开始遍历,或在非结尾元素结束遍历,或希望每次跳过一个元素,则for比forEach更方便控制。若循环中不同条件下索引可能增加n也可能减少n(最好别这样),则while比for更方便控制。
    视情况选择用哪种,一般用for循环。
链表+插入排序
typescript 复制代码
const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});
const inputLines = [];
class LineNode {
	val?: number; // default:public
   	next: LineNode | null = null;
   	last: LineNode | null = null;
	constructor(val?: number) {
		this.val = val;
		this.next = null;
		this.last = null;
	}
}
rl.on("line", function (line: string) {
    inputLines.push(line.trim());
});
rl.on("close", function () {
    const numsLength = parseInt(inputLines[0]);
    // 递增序列
    const lineHeadNode = new LineNode();

    // 遍历输入数
    // 若新输入数按顺序插入了nums,或与已有元素重合了,则处理下一个输入数
    for (let newNumIdx = 2; newNumIdx <= numsLength; newNumIdx++) {
        const newNum = parseInt(inputLines[newNumIdx]);
        // 遍历nums
        let compareNumIdx = nums.length - 1;
        while (lineHeadNode.last.) {
            const compareNum = nums[compareNumIdx];
            if (newNum === compareNum) {
            	// 退出nums遍历,去读取下一个输入数
                break;
            } else if (newNum > compareNum) {
            	// 插入新元素
                nums.splice(compareNumIdx + 1, 0, newNum);
                // 退出nums遍历,去读取下一个输入数
                break;
            } else {
                if (compareNumIdx === 0) {
                	// 在队首插入新元素
                    nums.unshift(newNum);
                    // 退出nums遍历,去读取下一个输入数
                	break;
                } else {
                	// 选取原被比较数的前一位作为新被比较数
                	compareNumIdx--;
                }
            }
        }
    }
    nums.forEach((num) => {
        console.log(num);
    });
});
相关推荐
chuxinweihui12 分钟前
数据结构——二叉树,堆
c语言·开发语言·数据结构·学习·算法·链表
zhuyixiangyyds14 分钟前
day36图像处理OpenCV
图像处理·笔记·学习
Mr__Miss16 分钟前
JVM学习笔记
jvm·笔记·学习
freexyn26 分钟前
Matlab自学笔记五十一:(推荐)输入参数的数量和可变数量的输入
笔记·算法·matlab
陈大大陈29 分钟前
基于 C++ 的用户认证系统开发:从注册登录到Redis 缓存优化
java·linux·开发语言·数据结构·c++·算法·缓存
纪元A梦32 分钟前
华为OD机试真题——通过软盘拷贝文件(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
java·javascript·c++·python·华为od·go·华为od机试题
看到我,请让我去学习38 分钟前
C语言基础(day0424)
c语言·开发语言·数据结构
数据分析螺丝钉1 小时前
LeetCode 252 会议室 III(Meeting Rooms III)题解与模拟面试
算法·leetcode·职场和发展
jmoych1 小时前
华为数字化转型“三阶十二步法“:战略驱动、系统布局与敏捷落地的实践框架
华为
小李独爱秋1 小时前
动态哈希映射深度指南:从基础到高阶实现与优化
数据结构·算法·哈希算法