剑指 Offer 56 - I. 数组中数字出现的次数

这篇具有很好参考价值的文章主要介绍了剑指 Offer 56 - I. 数组中数字出现的次数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

理想的人物不仅要在物质需要的满足上,还要在精神旨趣的满足上得到表现。        —— 黑格尔

目录

方法1:排序+指针

方法2:异或整个数组

题目:

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

示例 1:

输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]

示例 2:

输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]

剑指 Offer 56 - I. 数组中数字出现的次数

 

做题链接:剑指 Offer 56 - I. 数组中数字出现的次数

方法1:排序+指针

假如数组中的数字是:1,2,10,4,1,4,3,3。我们将这些数字进行排序,排序之后为1,1,2,3,3,4,4,10。我们的目标就是找出没有重复出现的两个数字,也就是2和10。

我们使用一个指针指向排序好数组的最后一个位置。
1.
然后看这个位置的数字和前一个位置的数字相不相等。如果相等,也就是没有找到我们的目标数字,然后指针向前移动两个位置,继续找,以此类推。

2.如果最后一个位置和前一个位置不相等,那么此时的最后一个位置也就是我们找到的第一个目标数字。然后指针向前移动一位,继续找前面的数字。

那么上述的话是什么意思呢?我们使用画图来理解。

剑指 Offer 56 - I. 数组中数字出现的次数

理解上述的话之后,我们直接上手写代码:

#include<stdlib.h>
int cmp_int(void* p1, void* p2)
{
	return *(int*)p1 - *(int*)p2;
}
int main()
{
	int arr[10] = { 0 };
	int n = 0;
	scanf("%d", &n);
	int i = 0;
	for (i = 0; i < n; i++)
	{
		scanf("%d", &arr[i]);
	}
	qsort(arr, n, sizeof(int), cmp_int);//这里使用快排的进行排序
	int right = n - 1;
	int j = 0;
	int k = 0;
	while (right > 0)
	{
		if (arr[right] != arr[right - 1])
		{//这里不相等,则找到了,直接打印出来
			printf("%d ", arr[right]);
			if (right == 1)
			{
				printf("%d", arr[0]);
			}
			right -= 1;//所以right-1,指向下一个位置
		}
		else
		{
			right -= 2;//否则right-2,指向下两个位置
		}
	}
	return 0;
}
if (right == 1)
{
 printf("%d", arr[0]);
}

这个代码如何理解呢?我们举个例子来讲解一下。
如果我们排序好的数组是 1 ,2,5,5,7,7,9,9。那么我们要找的数字就是1和2, 此时right指向的就是2,然后2和前面的1比较,显然2和1不相等,那么2就是我们要找到的数字。

然后right向前移动一位,指向1,然后1再和前面的数字进行比较,但是1前面没数字了,那么退出循环。但是1没有打印出来呀,所以我们单独打印第一个数字。这就是这个代码的意思。

 

方法2:异或整个数组

异或的计算法则是:二进制相同为0,不同为1。

有一个找单身狗的题:数组中其他数字均出现两次,有一个数字出现了一次,我们的目标就是找这个出现一次的数字,我们就可以使用异或全部的数字,得到的答案就是我们要找的数字,因为相同的数字异或为0,0和目标数字异或得到目标数字。

做题方法:这题我们一样可以使用异或整个数组来实现。相同的数字异或为0,最后的异或结果就是两个目标数字异或的结果。假如数组为1,2,10,4,1,4,3,3。

剑指 Offer 56 - I. 数组中数字出现的次数

废话不多说,直接上代码:

int* singleNumbers(int* nums, int numsSize, int* returnSize) {
	int* ans = (int*)calloc(2, sizeof(int));//calloc开辟的空间会自动赋值为0
	int temp = 0;
	int i = 0;
	for (i = 0; i < numsSize; i++)
	{
		temp ^= nums[i];//temp就是两个目标数字异或的结果
	}
	int pos = 0;//记录位置
	for (i = 0; i < 32; i++)
	{
		if (((temp >> i) & 1) == 1)//找二进制第一个1的位置
		{
			pos = i;
			break;
		}
	}
	//分组异或
	for (i = 0; i < numsSize; i++)
	{
		if (((nums[i] >> pos) & 1) == 1)
		{
			ans[0] ^= nums[i];
		}
		else
			ans[1] ^= nums[i];
	}
	*returnSize = 2;
	return ans;
}

剑指 Offer 56 - I. 数组中数字出现的次数 

希望能对你有所帮助,感谢你的支持。 文章来源地址https://www.toymoban.com/news/detail-415331.html

 

到了这里,关于剑指 Offer 56 - I. 数组中数字出现的次数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 剑指offer(C++)-JZ56:数组中只出现一次的两个数字(算法-位运算)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 数据范围:数组长度2≤n≤1000,数组中每个数

    2024年02月10日
    浏览(38)
  • 剑指 Offer 53 - I. 在排序数组中查找数字 I

    题目来源 剑指 Offer 53 - I. 在排序数组中查找数字 I 初始化: 左边界 i=0 ,右边界 j=nums.length−1。 循环二分: 当闭区间 [i, j] 无元素时跳出; 计算中点 m=(i+j)/2 (向下取整); 若 nums[m]target,则 target 在闭区间 [m+1,j] 中,因此执行 i=m+1; 若 nums[m]target,则 target 在闭区间 [i,m−

    2024年02月01日
    浏览(33)
  • 每天一道leetcode:剑指 Offer 53 - I. 在排序数组中查找数字 I(适合初学者&二分查找)

    统计一个数字在排序数组中出现的次数。 0 = nums.length = 10^5 -10^9 = nums[i] = 10^9 nums 是一个非递减数组 -10^9 = target = 10^9 使用两次二分查找找到target在数组中的左右边界,然后长度就是右边界减去左边界再加一,最后返回长度即可。   欢迎大家在评论区讨论,如有不懂的代码部分

    2024年02月14日
    浏览(42)
  • 【每日一题】Leetcode - 剑指 Offer 43. 1~n 整数中 1 出现的次数

    Leetcode - 剑指 Offer 43. 1~n 整数中 1 出现的次数 分解数字中的每一位,判断+记录 = 结果 But,超时了,下面是优化过程简介 空间换时间(爆内存) :n = 123456,则n{len-1} = 12345,其实走到n这里,说明n{len-1}这个数字我们一定已经知道了它有多少个1了,所以我们只需要记录保存下

    2024年02月11日
    浏览(37)
  • 剑指 Offer 14- I. 剪绳子

    剑指 Offer 14- I. 剪绳子 难度: m i d d l e color{orange}{middle} mi dd l e 题目描述 给你一根长度为 n n n 的绳子,请把绳子剪成整数长度的 m m m 段(m、n都是整数,n1并且m1),每段绳子的长度记为 k [ 0 ] , k [ 1 ] . . . k [ m − 1 ] k[0],k[1]...k[m-1] k [ 0 ] , k [ 1 ] ... k [ m − 1 ] 。请问 k [ 0 ] ∗

    2023年04月09日
    浏览(33)
  • 剑指 Offer 58 - I. 翻转单词顺序

    剑指 Offer 58 - I. 翻转单词顺序 不用内置方法 去除首尾空格和中间多余空格 翻转所有字符 翻转每个单词 用自带的 trim() 和 substring() ,要自己实现这两个方法也很简单。

    2024年02月11日
    浏览(26)
  • 【剑指 offer】旋转数组的最小数字

    ✨个人主页:bit me👇 ✨当前专栏:算法训练营👇 核心考点:数组理解,二分查找,临界条件 描述: 有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这

    2023年04月20日
    浏览(43)
  • 【剑指offer】数组中重复的数字

    👑专栏内容:力扣刷题 ⛪个人主页:子夜的星的主页 💕座右铭:前路未远,步履不停 剑指offer:数组中重复的数字 在一个长度为 n 的数组里的所有数字都在 0 0 0 到 n − 1 n-1 n − 1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复,也不知道每个数字重复了几

    2024年01月20日
    浏览(35)
  • 【剑指offer|1.数组中重复的数字】

    : 长度为n的数组nums中所有数字都在0~n-1范围内 返回任意一个重复的数字 总体时间复杂度和空间复杂度分析: 修改数组的方法: 因为有n个元素,每一个元素都在0~(n-1)范围内,如果元素不重复的话, 对数组重排之后,下标和元素值之间应该是一一对应的关系 但是因为

    2023年04月22日
    浏览(29)
  • 剑指offer03.数组中重复的数字

    看到这道题的第一眼想到的是先给它排序,然后双指针从左往右遍历,写了一个冒泡排序,但是我想到了应该会超时,因为冒泡时间复杂度是n的平方,输入大小时10000,肯定会超时,然后右又看了一下题目看到数字都是0-n-1,灵感一下子就来了,我先创建一个等大的自然数数

    2024年02月11日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包