算法只出现一次的数和计数排序

472 阅读3分钟

一周过的真快啊,在算法学习的道路上又踏出一步,今天想分享的是学习到的两个算法只出现一次的数和技术排序

只出现一次的数

题目描述 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。题目来源

示例 1:

输入: [2,2,1]
输出: 1

示例 2:

输入: [4,1,2,1,2]
输出: 4

我刚看到这个题时想弄个数组吧这个给记录下来,出现一次加次数加一个最后把次数是一的数反回去

var singleNumber = function(nums) {
 let len = nums.length;
 let newArr = [];
 let result;
 
 // 存储这个值并且count 设置为0
 for(let i = 0 ; i < len; i++) {
   let obj = { key:i, count:0, val: nums[i]}
   newArr.push(obj);
 }
 
 // 遍历输入的数如果出现一次 那么出现的次数累加
 for(let i = 0 ; i < len; i++) {
   for(let j = 0 ; j < len; j++) {
     if(nums[i] == newArr[j].val) {
       newArr[j].count ++;
     }
   }
 }

// 遍历存储的数返回累计次数为一的数
 newArr.map((item) => {
   if(item.count <= 1) {
     result = item.val;
   }
 });

 return result;
}

后来看了题解学习了一下人家用的方法是真的简单 最后实现代码如下

 var singleNumber = function(nums) {
    // 先预制一个数为0 
    let t = 0;
    // 然后和每一个数据进行异或操作
    for(let j = 0 ; j < nums.length; j++){
      t ^= nums[j];
        
    }
    // 最后返回异或操作
    return t;
 
 }; 

那么问题来了,什么是异或,模糊记得电工老师曾经教过 电路01,计算的汇编语言时代也是01 具体什么异或我还是不知道百科一下发现三个特点

  1. 0异或任何数=任何数
  2. 1异或任何数-任何数取反
  3. 任何数异或自己=把自己置0 那么代码中 let t = 0 就解释的通了 根据第一条特性 0异或任何数还是任何数,对原有数据不痛不痒啊 根据最后一条特性 任何数异或自己 把自己变成0 换句话说是不是就等于 只要出现超过一次就是0 根据 异或的规则验证一下 let arr = [2,2,1]; // 数据转换的时候有一个小技巧 8421 是16 进制 421 是八进制 example 2 = 010 421 因为是2 所有在2的数位上为1 example 3 = 011 421 因为是3 所有在2的数位上为1并且在1进置位上也要为1 这样才等于3 具体的 计算规则
                    011 = 0*21次方 + 2 * 21次方 + 1 * 20次方
        
        010 010 001
        000
        010   
            010
            010
            111
                001
                111
                001
                

let arr2 = [4,1,2,1,2]; 100 001 010 001 010

        100
        000
        100 
            001
            100
            101  
                010
                101
                111
                    001
                    111
                    110 
                        010
                        110
                        100

计数排序

  1. 这个适用数据量大单数数据区间小的排序 为啥写这句因为在学习的时候我只记住了这一句
  2. 感觉这个特别好理解和我第一题的那个想法类似,只不过把数据固定在某个区间了个人片见
function sumSort(arr){
    // 数组从0开始 但是我们0也要作为计数位置故此留出位置
    let len = arr.length+1;
    let newArr = [];

    // 生成计数位置
    for(let i = 0 ; i < len; i++){

        // 初始化计数位置上的次数为0
       let obj = { key: i, count: 0}
        for(let j = 0 ; j < len - 1; j++) {
            // 每个计数位置上出现一次 累加一次
            if(arr[j] == i){
             obj.count ++;
            }
        }
        newArr.push(obj);
    }

    let result = [];
   
    newArr.map((item) => {
        // 如果累加次数不为零那么说明有数值需要排序
        if(item.count) {
            // 出现一次推入一次
            for(let i = 0; i < item.count; i++) {
                result.push(item.key)
            }
        }
    })

    return result;
   
}

这个就类似于先生成一个table 然后往对应的单元格里放对应的数据,最后把放进去的数据按顺序一个个那出来。