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

题目

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

对于明明生成的 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);
    });
});
相关推荐
轻口味35 分钟前
【每日学点鸿蒙知识】低功耗蓝牙、指纹识别认证、读取raw文件示例、CommonEvent是否跨线程、定位参数解释等
华为·harmonyos
御承扬38 分钟前
从零开始开发纯血鸿蒙应用之实现内部文件处理页
华为·harmonyos·arkts·文本编辑·文本浏览
轻口味39 分钟前
【每日学点鸿蒙知识】ASON工具、自定义tabbar、musl、Text异常截断等
华为·harmonyos
Studying 开龙wu39 分钟前
机器学习算法的分类
算法·机器学习·分类·回归
Chenglin_Yu2 小时前
PCA降维算法详细推导
算法
liuhaikang2 小时前
鸿蒙MPChart图表自定义(六)在图表中绘制游标
华为·harmonyos
m0_678693333 小时前
深度学习笔记10-数据增强(Tensorflow)
笔记·深度学习·tensorflow
Wils0nEdwards5 小时前
Leetcode 最大正方形
算法·leetcode·职场和发展
红色的山茶花6 小时前
YOLOv10-1.1部分代码阅读笔记-autobackend.py
笔记·深度学习·yolo
milo.qu8 小时前
二、CSS基础
前端·javascript·css