LeetCode刷题笔记 - JavaScript(一)

剑指 Offer 57 - II. 和为s的连续正数序列
剑指 Offer 56 - I. 数组中数字出现的次数
剑指 Offer 56 - II. 数组中数字出现的次数 II

1.剑指 Offer 57 - II. 和为s的连续正数序列

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

题目大意:求和为target的所有连续正整数序列。

解题思路:最简单的写法就是枚举序列首部,然后循环求该序列首部连续和。考虑优化求和步骤,求区间[l,r]的数学公式为 ( ( l+r ) * ( r-l+1 ) ) / 2。利用这个公式我们可以将区间求和的时间优化为O(1),同时还可以跳过不必要求和的区间。

代码

	function(target) {
		const res = [];
		const temp = [];
		
		for(let l = 1, r = 2; l < r;) {
			const sum = ((l + r) * (r - l + 1)) / 2;
			if( sum === target) {
				temp.length = 0;
				for(let i = l; i <= r; i++) {
					temp.push(i);
				}
				res.push(temp);
			} else if(sum < taregt) {
				r++;
			} else {
				l++;
			}
		}
		return res;
	}

2.剑指 Offer 56 - I. 数组中数字出现的次数

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

题目大意:找出一个序列中只出现1次的两个数。

解题思路
首先,引入位运算的一些概念:
(1)异或运算符的运算规则是,相同为0,不同为1,也就是说两个不相同的数异或结果为1的数位是不同的
(2)任何数异或自己本身的结果都是0,比如5^5 === 0
(3)任何数异或0的结果都是0
利用概念(2),我们可以将整个数组中的数异或起来,然后最后得到的就是两个只出现了一次的值的异或值。然后我们需要将这两个数区分开来,这里就需要用到概念(1),即找出异或值中任意为1的一位。然后定义两个变量res1=0,res2=0。利用概念(3),将数位为1的数位异或到res1上,为0的数位异或到res2上,最终就可以求出只出现一次的两个数。

代码

	function(nums) {
		let res = 0;
		for(let item of nums) {
			res ^= item;
		}
		const flag = 1;
		while(!(res & flag)) {
			flag <<= 1;
		}
		let res1=0, res2 = 0;
		for(let item of nums) {
			if(item & flag) {
				res1 ^= item;
			} else {
				res2 ^= item;
			}
		}
		return [res1, res2];
	}

3.剑指 Offer 56 - II. 数组中数字出现的次数 II

在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。

题目大意:找出一个序列中只出现1次的那个数。

解题思路
假设数组中所有数都出现了三次,那么统计整个数组中各个数位上1出现的次数,肯定都是3的倍数。若此时在统计过程中,添加一个只出现了一次的数,那么必定会导致该数位上1的个数不是3的倍数,那么此时该数位就是只出现了一次的那个数的数位。此方法还可以应用到求出现n次的数组中出现一次的问题中,只需要改成n的倍数即可。

代码

	function(nums) {
		let res = 0;
		for(let i = 0; i < 32; i++) {
			const flag = 1 << i;
			let count = 0;
			for(const item of nums) {
				if(item & flag) count ++;
			}
			if(count % 3) res ^= flag;
		}
		return res;
	}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

volit_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值