给定一个数组,其中有n对成双的数字,只有一个是单独的数,求出这个数。
我记得以前看到过这题,用异或就能得出单独的数,因为成对的数字异或时结果一定是0,那么最后就像连连看一样把相似的都消掉留下那个唯一的。如果没看过的话,我的思路是先排序然后判断是否成双,应该也能过。
异或的代码如下:
int singleNumber(int* nums, int numsSize) {
int result = 0;
for (int i = 0; i < numsSize; i++) {
result = result ^ nums[i];
}
return result;
}
想着练练快排就把排序的解法也写了。没想到好久没写快排,在一些细节上没处理好导致排序老错:一个是在循环里要比较的点应该是num[low],而写的时候写成了num[l],而num[l]在循环中是会变化的。。。仔细一想这个错误也很白痴,因为快排是基于二分的排序就是跟第一个数比较,所以key点应该是首位数,而自己竟然写成了活动的节点;第二个是两个循环中比较时第一个循环比较完并交换后,第二个循环忽视了已经交换过的数字大小顺序已经变了,而自己还当做没交换时的大小把比较写反了。。。第三个是递归时左分和右分的上下边界实参和形参用错了,左分时上边界该用函数中的实参下边界用传过来的形参,右分时上边界用形参下边界用实参。。。
鼓捣完了快排,在求single number的时候也没注意target出现在首位或末尾的情况。。。最后排序的方法也过了,但耗时肯定比异或的方法多不少,不过验证了排序也是可行的,然后就是再次赞一下leet的测试用例,确实比较完善。。。
排序的如下:
void singleSort(int num[], int numsSize, int low, int high) {
if (low >= high)
return;
int temp = num[low];
int l = low, h = high;
while (l < h) {
while (temp <= num[h] && l < h)
h--;
num[l] = num[h];
while (num[l] <= temp && l < h)
l++;
num[h] = num[l];
}
num[l] = temp;
singleSort(num, numsSize, low, h - 1);
singleSort(num, numsSize, l + 1, high);
}
int singleNumber(int* nums, int numsSize) {
int result = 0;
// for (int i = 0; i < numsSize; i++) {
// result = result ^ nums[i];
// }
int i = 0, j = 1;
singleSort(nums, numsSize, 0, numsSize - 1);
for (; j < numsSize; i+=2, j=i+1) {
if (nums[i] != nums[j]) {
result = nums[i];
break;
}
}
if (j == numsSize && nums[j - 1] != nums[j - 1 - 1])
result = nums[numsSize - 1];
return result;
}