LeetCode-448. Find All Numbers Disappeared in an Array

来源:互联网 发布:java 日志级别 trace 编辑:程序博客网 时间:2024/06/06 00:41

Description:

这里写图片描述

Example 1:

这里写图片描述

Solution 1(C++):

这里写图片描述

Solution 2(C++):

这里写图片描述

算法分析:

这个题呢,Easy程度,不难,但是题目要求不适用Extra Space,就是说不要用额外的空间,说白了,就是只有一个返回数组可以用,其余操作都要在题目给的nums[]中完成。这就有意思了。按照我以前的习惯是利用类似与桶装排序的方法。对应的就是解法一的算法。而要少使用空间,就必须对nums本身动动手脚。
这里可以学习一二解法二。思考切入点如下:
1.要找出没有出现的数字的关键就是,将nums[i]的数字,与vector中的“顺序”联系起来。比如说解法一中,是将nums[i]的结果作为新的flag的位置索引index,让flag[index]的值发生变化。那么这里,我们不能有新的flag,不能借用第三方的值的变化来标识哪些nums[i]出现过。
2.既然不能借用第三方的值的变化,那就只能对nums[i]本身进行变化。考虑到nums[i]所有值都是正数,能变化的就是让他们变为负数。所以,我们可以让nums[i]对应的索引的数字变为负数。那么,最终遍历nums的时候,发现有负数,说明对应的索引出现过。
3.如果解决一个索引多次出现的情况?对应解法一,通过累加来完成,出现几次,就加几次1,如果最终flag的值为0,说明对应的nums没有出现过。那么解法二中,我们不需要计算出现多少次,只需要出现一次,和出现多次的变化是一样的。所以,就有了,出现一次及以上的次数,就让索引指向的数永远保持负数。
4.已经修改果断数,即变为了负数,如果做为新的索引进行其对应的值的查询?那就是用绝对值的方法来解决。
5.实例分析,举个例子来说:
[1,2,2,2].
5.1我们看nums[0]为1,说明1出现过,那么就让1-1的值作为索引,nums[0]的值变为负数,也就是nums[0]=-1。
5.2我们看nums[1]为2,说明2出现过,那么就让2-1的值作为索引,nums[1]的值变为负数,也就是nums[1]=-2。
5.3我们看nums[2]为2,说明2出现了第二次,那么就让2-1的值作为索引,本来应该让nums[1]的值变为负数,但经过5.2的变化后,nums[1]本来就是-2了,没有必要进行对出现次数的变化,所以保持-2就好了。
5.4我们看nums[3]为2,说明2出现了第三次,那么就让2-1的值作为索引,本来应该让nums[1]的值变为负数,但前两次拜年话,nums[1]本来就是-2了,没有必要进行对出现次数的变化,所以保持-2就好了。
5.5最终nums变为了[-1,-2,2,2],因为只有nums[0]与nums[1]变化了,所以意味着1,2出现过,而nums[2]与nums[3]仍为正数,说明3、4没出现过。

程序分析:

1.通过i获得要查询的数的索引,并且通过绝对值函数abs(),保证已经变化了的数还能起到索引的作用,比如说,之前的例子。

 int m = abs(nums[i])-1;

2.返回绝对值的负值:

nums[m] = nums[m]>0 ? -nums[m] : nums[m];

这里用到了<表达式1>?<表达式2>:<表达式3>这样的句子。很简单:
表达式1为真,返回表达式2;表达式1为假,返回表达式3。
变形:取绝对值函数:

nums[m] = nums[m]>0 ? nums[m] : -nums[m];
原创粉丝点击