let num = 0
nums.forEach(item => {
obj[item] = obj[item] ? obj[item] + 1 : 1
if(obj[item] > len / 2) num = item
})
return num
};
时间复杂度: O(n) 遍历一次 空间复杂度: O(n) obj中属性最多为 n/2 个
解法三:投票算法
该算法在其局部变量中维护一个序列元素和一个计数器,计数器最初为零。然后,它一次一个地处理序列的元素。处理元素x时,如果计数器为零,则算法将x存储为其维护的序列元素,并将计数器设置为1。否则,它将x与存储的元素进行比较,并使计数器递增(如果相等)或递减计数器(不相等)。
这里有两个先觉条件要明确:
出现超过一半以上(n/2)的元素有且只有一个;
这个元素一定存在
原理解析
为了解析算法的原理,我们只要考虑存在多数元素的情况即可,因为第二趟扫描可以检测出不存在多数元素的情况。
举个例子,我们的输入数组为[1,1,0,0,0,1,0],那么0就是多数元素。首先,candidate被设置为第一个元素1,count也变成1,由于1不是多数元素,所以当扫描到数组某个位置时,count一定会减为0。在我们的例子中,当扫描到第四个位置时,count变成0.
count 值变化过程:[1,2,1,0……
当count变成0时,对于每一个出现的1,我们都用一个0与其进行抵消,所以我们消耗掉了与其一样多的0,而0是多数元素,这意味着当扫描到第四个位置时,我们已经最大程度的消耗掉了多数元素。
var majorityElement = function(nums) {
let count = 1;
let majority = nums[0];
for(let i = 1; i < nums.length; i++) {
if (count === 0) {
majority = nums[i];
}
if (nums[i] === majority) {
count ++;
} else {
count --;
}
}
return majority;
};
2.只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
解法一:位运算
n ^ n === 0 且 n ^ 0 === n
/**
-
@param {number[]} nums
-
@return {number}
*/
var singleNumber = function(nums) {
let ans = 0;
for(const num of nums) {
ans ^= num;
}
return ans;
};
解法二:排序
因为只存在一个不重复的数字其他都两两出现,所以进行排序后,相同的数字必定是连续的,所以只要判断是否连续
/**
-
@param {number[]} nums
-
@return {number}
*/
var singleNumber = function(nums) {
nums = nums.sort((a, b) => {
return a-b
})
for (let i = 0; i<nums.length;i+=2){
if (nums[i] != nums[i+1]) {
return nums[i]
}
}
};
解法三:暴力法,但是慢
暴力法,根据索引来判断。indexOf从左往右找,lastIndexOf从右往左找。当元素只出现一次时,无论从哪里找起,索引都是相同的。结果返回元素即可
/**
-
@param {number[]} nums
-
@return {number}
*/
var singleNumber = function(nums) {
for (let item of nums) {
if (nums.indexOf(item) === nums.lastIndexOf(item))
return item
}
};
3.只出现一次的数字 II
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三
次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,3,2]
输出: 3
示例 2:
输入: [0,1,0,1,0,1,99]
输出: 99
解法一:位运算
1.位运算求解此题; 2.如果把所有出现三次的数字的二进制表示的每一位加起来,那么每一位都能被3整除; 3.如果某一位的和能被3整除,那么只出现一次数字的二进制位中对应的那一位就是0,否则就是1; 4.完结。
得到的启发,把每个32位的位置都记录一遍
public int singleNumber(int[] nums) {
if (nums == null || nums.length <= 0)
throw new RuntimeException(“数组不合法”);
int[] bits = new int[32];
for (int j = 0; j < bits.length; j++) {
for (int i = 0; i < nums.length; i++) { // 每一位数字对应的0或1加起来
int num = nums[i] >> j;
bits[j] += (num & 1);
}
}
int result = 0;
for (int i = bits.length - 1; i >= 0; i–) {
result <<= 1;
result += bits[i] % 3;
}
return result;
}
解法二:排序
解题思路:
-
排序,升序或降序均可
-
循环,每三组进行相加,并判断是否等于第一项的三倍
-
相同的话说明三个数字相同
-
不同的话,说明肯定存在不同的数字
-
进行异或
-
循环完后还没有,则最后一个是
var singleNumber = function(nums) {
nums = nums.sort((a, b) => a - b);
for(var i = 2; i < nums.length; i += 3){
if((nums[i] + nums[i - 1] + nums[i - 2]) !== nums[i]*3){
return nums[i] ^ nums[i - 1] ^ nums[i - 2]
}
}
return nums[nums.length - 1];
};
解法三:暴力法,但是慢
跟上面一题一样。
4.只出现一次的数字 III
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。找出只出现一次的那两个元素。
示例 :
输入: [1,2,1,3,2,5]
输出: [3,5]
注意:
结果输出的顺序并不重要,对于上面的例子, [5, 3] 也是正确答案。你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?
解法一:位运算
异或 + & 如果异或还不太懂的可以先看下相关的几个题目先把异或搞懂先
-
第一步:所有数异或,所有数异或之后的值就是两个只出现一次的数a,b异或后的值s。
-
第二步:那我们用s & (-s) 可以得出s最低位(也就是最右边)为1的bit位(这个操作不太会事先知道)对应的数k,
这里有一个很关键点就是:这个为1的bit位肯定只来之a.b其中的一个数字中的对应二进制位的1,这里有点卡主理解,比如我们把数字转成二进制运算看下:
a:1 -> 0001
b:2 -> 0010 => 0011. 不全为1的bit为进行异或操作就为1,这是异或的基本流程,然后我们操作s & (-s)之后得到的是0001,可以看到这个1是来之数字a的
-
第三步:我们得到s&(-s)之后在对所有数进行&操作的话,就意味着可以将a和b区分在0和1的两个组,至于其他的数字如果相同的数字自然会分到一个组,可以用纸笔写下整个过程
-
第四步:经过第三步之后就变成了只有一个数字存在一个其他都存在两个的数组(也就变成题目:136. 只出现一次的数字), 然后我们分别对两个组的所有数字再进行异或之后不就得到了要求的那两个数了嘛。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
算法刷题
大厂面试还是很注重算法题的,尤其是字节跳动,算法是问的比较多的,关于算法,推荐《LeetCode》和《算法的乐趣》,这两本我也有电子版,字节跳动、阿里、美团等大厂面试题(含答案+解析)、学习笔记、Xmind思维导图均可以分享给大家学习。
写在最后
最后,对所以做Java的朋友提几点建议,也是我的个人心得:
-
疯狂编程
-
学习效果可视化
-
写博客
-
阅读优秀代码
-
心态调整
合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-tq8qxstY-1711873443784)]
算法刷题
大厂面试还是很注重算法题的,尤其是字节跳动,算法是问的比较多的,关于算法,推荐《LeetCode》和《算法的乐趣》,这两本我也有电子版,字节跳动、阿里、美团等大厂面试题(含答案+解析)、学习笔记、Xmind思维导图均可以分享给大家学习。
写在最后
最后,对所以做Java的朋友提几点建议,也是我的个人心得:
-
疯狂编程
-
学习效果可视化
-
写博客
-
阅读优秀代码
-
心态调整