欢迎光临小站:致橡树
两数之和
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
-
2 <= nums.length <= 104
-
-109 <= nums[i] <= 109
-
-109 <= target <= 109
-
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2)
的算法吗?
解题思路
最容易想到的就是for循环大法,你既然要找两个数,那就两个for循环伺候,最差的结果就是时间复杂度是O(N2)。
class Solution {
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
return new int[] { i, j };
}
}
}
return null;
}
}
既然是算法题,那就一定会留一个只for循环一遍的招。最常见的方法是空间换时间,给一个索引,索引好遍历过的值,那么在遍历接下来的值时,都去索引里先配对一下是否存在,存在就结束。
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(target - nums[i])) {
return new int[] { map.get(target - nums[i]), i };
} else {
map.put(nums[i],i);
}
}
return null;
}
}
结果也很明显,55ms降到2ms,内存略微增加。
移动零
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:
输入: nums = [0]
输出: [0]
提示:
-
1 <= nums.length <= 104
-
-231 <= nums[i] <= 231 - 1
进阶:你能尽量减少完成的操作次数吗?
解题思路
能一次遍历解决的就不两次,题中涉及元素的移动(交换),想到双指针,然后需要把非零的往左移动。那么其中快指针负责持续遍历,慢指针如果遍历到零值,需要稍作等候与快指针的值交换,达到慢指针的左侧不可能出现零值的情况。
class Solution {
public void moveZeroes(int[] nums) {
int slow = 0;
int fast = 0;
for (; fast < nums.length; fast++) {
if (nums[slow] == 0 && nums[slow] !=nums[fast]) {
int temp = nums[slow];
nums[slow] = nums[fast];
nums[fast] = temp;
}
if(nums[slow] != 0){
slow++;
}
}
}
}