《剑指offer》第一篇---消失的数字
Posted 花嵩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《剑指offer》第一篇---消失的数字相关的知识,希望对你有一定的参考价值。
文章目录
前言:
博主实力有限,博文有什么错误,望各位大佬,不吝赐教,非常感谢!
这是博主的新专栏《剑指offer》第一篇,希望各位大佬多多支持,感谢!
如果对按位与&,按位异或^ ,按位或|,&&且,||或,不是太明白的见我另外一篇博客:
题目
消失的数字
一个数组中含有从0到20的
所有
数字,但是数组中缺少了0到20中的一个数,请你找出这个消失的数字
高效方法一:双目操作符按位异或^
补充
- 按位异或^ 的规则是:
exp:a^b
比较a与b中二进制
补码
(!!!)中每位,相同那么新形成的二进制
对应位为0,不相同的为1exp:
a= 1;b= 3;
a的补码:
00000000 00000000 00000000 00000001
b的补码:
00000000 00000000 00000000 00000011
a^b后的新的二进制补码是:
00000000 00000000 00000000 00000010
**按位异或的一些规律:**
(!!!)
0与任何数异或都是任何数
**1^ 2 ^ 3 ^2 ^ 3 =1**
这是理解本题目的
**关键点**
!!!
思路:
正是因为1 ^ 2 ^ 3 ^4 ^5 ^ 2 ^3 ^ 4^ 5=1
因此对于本题;将数组中所有数全部 按位异或
^
到一起- x=arr[0]^ arr[1]^ arr[2]^ … arr[19]
之后再将0到20的数字异或到一起
那么最后,
x
必然是那个消失的数
毕竟0到20重复的数都^没了
代码
int main()
{
int x = 0;//用于存放按位异或的数据
int arr[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20 };
int sz = sizeof(arr) / sizeof(*arr);
for (int i = 0; i < sz; i++)
{
x ^= arr[i];
}
//x=0^1^2^3....^20;
for ( int i = 0; i < 21; i++)
{
x ^= i;
}
//这次for循环后,连续的^中,相同的数据都被抵消,只剩下一个消失的那个数
printf("%d\\n", x);
}
时间复杂度:0(N),空间复杂度:0(1)
优点:算法效率高
缺点:
只能用于查找消失的一个数,对于消失的数字过多情况不能处理,即使分组也不好。-----分组的思想在我另外一篇博客:单身狗
一般方法:折半查找法,与对比排序法
二分查找法:
- 思路
依次拿0到20中的数字 在数组中用
二分查找
的方法查找
- 代码:
//折半查找 for (int i = 0; i <= 20; i++)//i为要查找的数 { int left = 0;//存放数组左边下标 int right = sz - 1;//存放数组右边下标 int mid = 0;//数组中间数据的下标,之所以定义在外面是因为,每次for循环,、 //mid生命周期结束,这样就可以重置mid while (left <= right) { mid = (left + right) / 2; if (arr[mid] > i)//说明要找的数据在mid的左边,排序后,左边的数据都小于arr[mid] { right = mid - 1; } else if (arr[mid] < i)//说明要找的数据在mid的右边,排序后,右边的数据都小于arr[mid] { left = mid + 1; } else { break;//break,只能结束一层循环即while, } } if (left > right)//如果i没有在数组中找到就输出I { printf("%d\\n", i); } } }
时间复杂度:0(N2)空间复杂度:0(1)
优点可以处理消失数字多的情况。
缺点必须要对数组排序。
对比排序法:
- 思想:将数组排序后,将0到20的数组依次与数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6L4g3Ptr-1631111664941)(前言:.assets/image-20210908164408529-16310906497221.png)]
代码:
int main() { int arr[] = { 16,17,18,19,0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,20 }; int sz = sizeof(arr) / sizeof(*arr);//计算数组长度 //选择法排序 for (int i = 0; i < sz - 1; i++)//选择法排序数组的思想就是, //拿第i个元素,将其与之后的数据进行比较, //拿到最小数据的下标。 { int min = i;//用于存放下标 for (int j = i + 1; j < sz; j++) { if (arr[j] < arr[min]) { min = j; } }//通过此层循环,min会得到数据最小的数组下标 if (min != i)//如果min得到下标不是i就交换下标i与下标min的值 { int tmp = arr[i]; arr[i] = arr[min]; arr[min] = tmp; } } int flag = 0;//记录数组下标 for (int i = 0; i < 21; i++) { if (i ^ arr[flag])//^后如果不相等,那么异或后就是非0,也就是i为缺少的数字 { printf("%d\\n",i); } else { flag++; } } }
时间复杂度:0(N2),空间复杂度:0(1)
优点可以实现 消失的数字多的情况
缺点:也是必须对数组排序。
总结:
- 博主目前没想到,不用按位异或的方法,不对数组排序的情况下,找到消失的数字的方法。
- 若有那为大佬,知道这种不排序就可以找到的消失的数字方法,希望大佬能留言,非常感谢!
以上是关于《剑指offer》第一篇---消失的数字的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段