技巧(5) --hot 100 in leetcode
只出现一次的数字
算法概述
本题要求为在给出的由一个出现一次的数字和其他出现两次的数字中找到那个出现一次的(要求时间复杂度为O(n),空间复杂度为O(1))。使用 位运算 解决。
JAVA
1 | class Solution { |
C++
1 | // 异或运算是一样的 |
注意
异或运算^
的运算规律如下:
- 与相同数异或,得到0
- 与0异或,得到自身( 等同于二进制的数中的每一位都与0异或,那么每一位异或得到的就是原本的0或1 )
位运算也很重要
多数元素
算法概述
本题要求为返回其中多数元素(出现频次大于一半),要求时间复杂度和空间复杂度与上题一致。使用Boyer-Moore 投票算法。
JAVA
1 | class Solution { |
C++
1 | // 总体思路一致 |
注意
众数的频次绝对会比其他所有的数频次加起来高(大于一半),所以不管怎么排列,只要存在众数,count
本质上是众数的频次减去其他所有数的频次,一定为正,且所属的candidate
也会在遍历完后成为众数。
颜色分类
算法概述
本题要求将相同颜色 原地 排列相邻,不同颜色之间遵照顺序(一共三种颜色,用012表示),复杂度要求与上题一致。使用 双指针 解决。
JAVA
1 | class Solution { |
C++
1 | // 思路一致,用vector,不用指针,数字索引就行 |
注意
也就是说p1
始终指向最后一个1的位置 ,p0
始终指向最后一个0 。代码中,只有 碰到0才会交换并移动p0指针 ,所以p0
始终指向最后一个0,而因为 碰到1和0都需要移动p1指针 ,但是 1的排序是乱的,所以p1
始终指向的是 最后一个1应该在的位置 ,而不是 真正的最后一个1 ,这是因为 碰到0移动产生的偏差 ,那就还需要 交换当前索引和p1 来补齐,因为 p1随p0一起移动的次数就是p1少交换的次数 ,所以只需要if (p0 < p1)
一个判断再做交换就足够了。
这道题的核心就是 管理不同指针之间的相对关系 ,需要着重理解增强代码设计能力。
下一个排列
算法概述
本题要求为找出给出数组的下一个排列(就是比当前数大的其他排列中最小的那个排列),要求原地,空间复杂度要求常数。也就是要 找最靠右的一个顺序对,左边的是小的,右边的是大的,然后交换它们 。
- 时间复杂度为O(n):两次遍历
JAVA
1 | class Solution { |
C++
1 | // 一样的思路 |
注意
主要难点是理解题目。还有要记得 反转 。
while (i >= 0 && nums[i] >= nums[i + 1])
:这个循环是用于 将升序遍历完while (j >= 0 && nums[i] >= nums[j])
:这个循环是用于 将小于i值的元素遍历完
非常神奇的写法
寻找重复数
算法概述
本题要求为在给定的只有一个重复数的数组中找到那个重复数,不修改原数组且空间复杂度为常数级。可以用位运算解决,但更快的还是 快慢指针 。但这个 快慢指针 是基于 索引 的,还不是基于速度的。
- 时间复杂度为O(n)
JAVA
1 | class Solution { |
C++
1 | // 一样的 |
注意
解法核心在于 基于索引移动跳转 ,因为有重复元素,所以一定能通过跳转索引的方式找到环。然后,可以确定的是,快慢指针此时相遇时 是在环内 ,因为值一样,但不能确定入环点。此时需要 将慢指针放回起始点,不动快指针 ,让它们 同频移动 ,就会在入环点相遇(可参考“环形链表II”的计算)。注意,第一个循环 不能确定重复值 ,因为是 索引形成的环 。
- Title: 技巧(5) --hot 100 in leetcode
- Author: tobegold574
- Created at : 2024-11-28 00:19:45
- Updated at : 2024-12-02 13:32:52
- Link: https://tobegold574.me/2024/11/28/技巧-5-hot-100-in-leetcode/
- License: This work is licensed under CC BY-NC-SA 4.0.