public class Solution {
public int missingNumber(int[] nums) {
int N = nums.length;
int sum = 0;
for(int num : nums) sum += num;
return (N + 1) * N / 2 - sum;
}
}
这题挺 tricky 的,到现在也是记的九章的答案。
思路就是不断试图把当前元素替换到其正确的位置上;如果目标位置元素已经正确则 do nothing,如果目标位置越界,也 do nothing. 每次交换之后指针位置不动,继续试图新一轮替换。这样一次循环之后,所有能被放到正确位置的元素,都会被放过去,而第一个位置和值不匹配的元素就是我们要寻找的目标。
注意要点:
当前元素的目标位置 index 有可能越上下界,多加两个判断条件;
如果真是 swap 了,不代表当前元素一定是正确位置,指针不要动(或者说在 for loop 里面要 i--)
public class Solution {
public int firstMissingPositive(int[] nums) {
for(int i = 0; i < nums.length; i++){
if(nums[i] != i + 1 && nums[i] - 1 >= 0 && nums[i] - 1 < nums.length && nums[nums[i] - 1] != nums[i]){
swap(nums, i, nums[i] - 1);
i--;
}
}
for(int i = 0; i < nums.length; i++){
if(nums[i] != i + 1) return i + 1;
}
return nums.length + 1;
}
private void swap(int[] nums, int a, int b){
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
}
public class Solution {
public List<String> findMissingRanges(int[] nums, int lower, int upper) {
List<String> list = new ArrayList<>();
for(int i = 0; i < nums.length; i++){
int candidate = nums[i] - 1;
if(candidate == lower) list.add("" + candidate);
else if(candidate > lower) list.add("" + lower + "->" + candidate);
lower = Math.max(lower, nums[i] + 1);
}
if(lower == upper) list.add("" + lower);
else if(lower < upper) list.add("" + lower + "->" + upper);
return list;
}
}
这题是一个道理,我们依然用 first missing positive 的做法,把每个数试图换到它对应的位置上;然后 nums 数组最后的那个元素,一定是 duplicate element,因为其他元素都归位之后,它没地方去。因为如果最后一个元素是唯一元素的话,它一定会被置换到正确位置上。
好吧,写完了我才发现不让修改原数组= =
public class Solution {
public int findDuplicate(int[] nums) {
for(int i = 0; i < nums.length; i++){
if(nums[i] != i + 1 && nums[i] - 1 >= 0 && nums[i] - 1 < nums.length && nums[nums[i] - 1] != nums[i]){
swap(nums, i, nums[i] - 1);
i--;
}
}
return nums[nums.length - 1];
}
private void swap(int[] nums, int a, int b){
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
}
这题还有另一种很妖孽的写法,就是把它当成 LinkedList 做。。
那么这道题又跟Find the Duplicate Number有什么关系呢? 在table中每个元素存储的是table index,根据其跳转,其实就是把table中的元素作为指针来使用。就像我们在上题中也是在child node中存parent node的index,并做跳转。 我们结合Find the Duplicate Number这道题来看。这道题讨论区most voted的解法即是一个国人大神把它转化为了Linked List Cycle来做。 find linked list cycle是一道大家都很熟悉的题。而国人大神的解法就是把given array中的每一个元素当作指针来用跳转到下一个元素。 我们用A[1, 4, 3, 2, 5, 2, 6]来做例:
当我们扫到A[0]时,A[0] == 1,把它作为指针来使用,我们跳到A[1];
A[1] == 4, 跳到A[4];
A[4] == 5, 跳到A[5];
A[5] == 2, 跳到A[2];
A[2] == 3, 跳到A[3];
A[3] == 2, 开始循环...
这道题之所以可以把元素作为指针来使用当然也是题干出的巧。
这里要注意初始化问题,fast 要初始化成 nums[nums[0]],不然死循环。
public class Solution {
public int findDuplicate(int[] nums) {
if (nums.length > 1)
{
int slow = nums[0];
int fast = nums[nums[0]];
while (slow != fast)
{
slow = nums[slow];
fast = nums[nums[fast]];
}
fast = 0;
while (fast != slow)
{
fast = nums[fast];
slow = nums[slow];
}
return slow;
}
return -1;
}
}