1._283_移动零
标签:数组、双指针
思路:如果扫描将0元素交换到数组尾部,会打乱顺序。所以应该将非零元素向前交换。
1)双指针,一个指针i用来扫描数组,一个指针cur指向可以交换的位置。
2)i指针指向0时,跳过,i++,但遇到非零元素时,交换i位置与cur位置的元素,并将i位置置为0, cur++;
3)注意情况,cur与i相等时,cur++,i++
代码:
public void moveZeroes(int[] nums) {
for(int i = 0,cur = 0;i < nums.length;i++){
if(nums[i] == 0) continue;
if(cur != i){
nums[cur] = nums[i];
nums[i] = 0;
}
cur++;
}
}
2.两数之和
标签:数组、哈希表
思路:若存在扫描到后面,想利用O(1)时间看之前扫描过的元素是否存在某个值,可以用哈希 表,哈希表检查key是否存在时O(1)级别。
代码:
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0;i < nums.length;i++){
Integer idx = map.get(target - nums[i]);
if(idx != null){
return new int[]{idx,i};
}
map.put(nums[i],i);
}
return null;
}
3._15_三数之和
标签:数组、双指针、排序
思路:
①暴力法 枚举每一个三元组 时间复杂度 O(n³) 空间O(1)
②优化:
先排序O(nlogn)
1)设置三个指针i,l,r, i 固定用来做扫描,l左指针,r右指针。
2)每一轮扫描,l = i + 1,r = nums.length - 1;当三个指针指向的元素的总和 < 0 时,l++;当偏大时r--,每一轮扫描的结束条件时 l >= r;
3)去重:当下一个i 指向的元素与此前的 i 指向元素相同时,跳过。当 l + 1指向的和 l 指向的相同时,跳过,直接l++,当 r - 1指向的和 r 指向的相同时,跳过,直接 r--.
代码:
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
if (nums == null) return list;
if (nums.length < 3) {
return list;
}
Arrays.sort(nums);
for (int i = 0; i <= nums.length - 3; i++) {
if (nums[i] == nums[i - 1]) continue;
int target = -nums[i];
int l = i + 1;
int r = nums.length - 1;
while (l < r) {
if (nums[l] + nums[r] == target) {
list.add(Arrays.asList(nums[i], nums[l], nums[r]));
// 去重
while(l < r && nums[l] == nums[l + 1]) l++;
while(l < r && nums[r] == nums[r - 1]) r--;
// 往中间逼近
l++;
r--;
} else if (nums[l] + nums[r] < target) { //结果偏小
l++;
} else {
r--;
}
}
}
return list;
}
标签:递归、数学、快速幂
思想:① 将n个x进行相乘 时间(n) 空间O(n)
② 快速幂
1)递归
代码:
public double myPow1(double x, int n) {
if(n == 1) return 0;
if(n == -1) return 1 / x;
// 是否为奇数
boolean odd = (n & 1) == 1;
double half = myPow(x,n >> 1);
half *= half;
return odd ? half*x :half;
}
时间复杂度 O(logn) 空间复杂度O(logn)
2)快速幂+非递归
代码:
public double myPow(double x, int n) {
double res = 1.0;
boolean neg = n < 0;
long y = neg ? -((long)n) : n;
while(y > 0){
boolean odd = (y & 1) == 1;
// 如果最后一个二进制位是1,就雷澄上x
if(odd){
res *= x;
}
x *= x;
// 舍弃掉最后一个二进制位
y >>= 1;
}
return neg ? (1 / res) : res;
}
时间复杂度:O(logn) 空间复杂度:O(1)