一周过的真快啊,在算法学习的道路上又踏出一步,今天想分享的是学习到的两个算法只出现一次的数和技术排序
只出现一次的数
题目描述 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。题目来源
示例 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 具体什么异或我还是不知道百科一下发现三个特点
- 0异或任何数=任何数
- 1异或任何数-任何数取反
- 任何数异或自己=把自己置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*2的1次方 + 2 * 2的1次方 + 1 * 2的0次方
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
计数排序
- 这个适用数据量大单数数据区间小的排序 为啥写这句因为在学习的时候我只记住了这一句
- 感觉这个特别好理解和我第一题的那个想法类似,只不过把数据固定在某个区间了个人片见
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 然后往对应的单元格里放对应的数据,最后把放进去的数据按顺序一个个那出来。