力扣爆刷第102天之hot100五连刷96-100
文章目录
- 力扣爆刷第102天之hot100五连刷96-100
- 一、136. 只出现一次的数字
- 二、169. 多数元素
- 三、75. 颜色分类
- 四、31. 下一个排列
- 五、287. 寻找重复数
一、136. 只出现一次的数字
题目链接:https://leetcode.cn/problems/single-number/description/?envType=study-plan-v2&envId=top-100-liked
思路:本题利用数学技巧,利用异或运算,一个数与0异或运算的结果还是它自身,此外,不同异或为1,相同为0,不同数异或会有一些大小变化,再进行相同数异或会减小掉变化。
class Solution {public int singleNumber(int[] nums) {int res = 0;for(int n : nums) {res ^= n;}return res;}
}
二、169. 多数元素
题目链接:https://leetcode.cn/problems/majority-element/description/?envType=study-plan-v2&envId=top-100-liked
思路:投票算法,当前数如果重复出现则加1,出现别的数则减1,为0换下一个数。
class Solution {public int majorityElement(int[] nums) {int count = 0, res = 0;for(int n : nums) {if(count == 0) {res = n;}count += n == res ? 1 : -1;}return res;}
}
三、75. 颜色分类
题目链接:https://leetcode.cn/problems/sort-colors/description/?envType=study-plan-v2&envId=top-100-liked
思路:3个数要排序,先0和1交换排序,然后再1和2交换排序。
class Solution {public void sortColors(int[] nums) {int zero = 0;for(int i = 0; i < nums.length; i++) {if(nums[i] == 0) {int temp = nums[zero];nums[zero] = nums[i];nums[i] = temp;zero++;}}int one = zero;for(int i = zero; i < nums.length; i++) {if(nums[i] == 1) {int temp = nums[one];nums[one] = nums[i];nums[i] = temp;one++;}}}
}
四、31. 下一个排列
题目链接:https://leetcode.cn/problems/next-permutation/description/?envType=study-plan-v2&envId=top-100-liked
思路:求下一个排列,是求下一个最小的大于它的值,基本原理从下图的5, 7, 6, 4处进行寻找,寻找最小的一个大于它的数,自然要从右边开始找,找第一个凹陷处,nums[i] < nums[i+1],此时i= 5,然后再从右边找第一个大于5 的数,为6,也就是nums[j]>nums[i],此刻这个6就是最小的一个大于它的数,然后交换,交换后[i, end]为单调递减,然后翻转即可。
class Solution {public void nextPermutation(int[] nums) {int i = nums.length - 2;while(i >= 0 && nums[i] >= nums[i+1]) {i--;}if(i >= 0) {for(int j = nums.length-1; j >= 0; j--) {if(nums[j] > nums[i]) {swap(nums, i, j);break;}}}reverse(nums, i+1, nums.length-1);}void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}void reverse(int[] nums, int i, int j) {while(i < j) {swap(nums, i, j);i++;j--;}}
}
五、287. 寻找重复数
题目链接:https://leetcode.cn/problems/find-the-duplicate-number/description/?envType=study-plan-v2&envId=top-100-liked
思路:寻找重复数,给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n)。这个是题目的描述,说明最大的数作为索引,也仅仅是数组结尾,所以可以把数组元素和索引建立联系,构建逻辑上的循环数组,和链表上的循环数组一样,使用快慢指针,慢的走一步,快的走两步,相遇就是环的入口,只不过此时拿到的是数组里的数,然后再有一个从起点出发,相遇即可拿到环的入口。
class Solution {public int findDuplicate(int[] nums) {int slow = 0, fast = 0;slow = nums[slow];fast = nums[nums[fast]];while(slow != fast) {slow = nums[slow];fast = nums[nums[fast]];}int one = 0;while(one != slow) {one = nums[one];slow = nums[slow];}return one;}
}