AcWing15:不修改数组找出重复的数字
Posted 劭兮劭兮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing15:不修改数组找出重复的数字相关的知识,希望对你有一定的参考价值。
问题
原题链接
原题链接:不修改数组找出重复的数字
个人思路
自己思路:
双层for循环,把整个数组遍历一遍,每一个元素都与其后面的元素比较,如果有相等的元素,结束循环;
java实现
class Solution {
// public int duplicateInArray(int[] nums) {
// }
public static void main(String[] args) {
int[] nums = {2,3,5,4,3,2,6,7};
duplicateInArray(nums);
}
public static int duplicateInArray(int[] nums) {
int temp=0;
for(int i = 0;i<nums.length-1;i++) {
for(int j=i+1;j<nums.length;j++) {
if(nums[i] == nums[j]) {
temp = nums[i];
}
}
}
return temp;
}
}
大佬思路
(自己的解题思路比较菜,所以一般会学习一下大佬的思路)
(分治,抽屉原理) O(nlogn)
抽屉原理:n+1 个苹果放在 n 个抽屉里,那么至少有一个抽屉中会放两个苹果。
一共有 n+1 个数,每个数的取值范围是1到n,所以至少会有一个数出现两次。
采用分治的思想,将每个数的取值的区间[1, n]划分成[1, (n+1)/2]和[(n+1)/2+1, n]两个子区间,然后分别统计两个区间中数的个数。
注意:这里的区间是指 数的取值范围,而不是 数组下标。
划分之后,左右两个区间里一定至少存在一个区间,区间中数的个数大于区间长度。(这个可以用反证法来说明:如果两个区间中数的个数都小于等于区间长度,那么整个区间中数的个数就小于等于n,和有n+1个数矛盾。)
因此我们可以把问题划归到左右两个子区间中的一个,而且由于区间中数的个数大于区间长度,根据抽屉原理,在这个子区间中一定存在某个数出现了两次。
依次类推,每次我们可以把区间长度缩小一半,直到区间长度为1时,我们就找到了答案。
复杂度分析
- 时间复杂度:每次会将区间长度缩小一半,一共会缩小 O(logn)次;每次统计两个子区间中的数时需要遍历整个数组,时间复杂度是O(n) ; 所以总时间复杂度是 O(nlogn)。
- 空间复杂度:代码中没有用到额外的数组,所以额外的空间复杂度是 O(1)O(1)。
JAVA实现一
class Solution {
public static void main(String[] args) {
int[] nums = {2,3,5,4,3,2,6,7};
duplicateInArray(nums);
}
public static int duplicateInArray(int[] nums) {
int start = 1;
int end = nums.length-1;
while(start<end) {
int mid = (end+start)/2;
int count=0;
for(int i = 0;i<nums.length;i++) {
if(nums[i]>=start && nums[i]<=mid) {
count++;
}
}
if(count > mid-start+1) {
end = mid;
}else {
start = mid + 1;
}
}
return end;
}
}
JAVA实现二
class Solution {
public static void main(String[] args) {
int[] nums = {2,3,5,4,3,2,6,7};
duplicateInArray(nums);
}
public static int duplicateInArray(int[] nums) {
int start = 1;
int end = nums.length-1;
while(start<end) {
int mid = (end+start)/2;
int count=0;
for(int i = 0;i<nums.length;i++) {
if(nums[i]<=end && nums[i]>=mid+1) {
count++;
}
}
if(count > end-mid) {
start = mid + 1;
}else {
end = mid;
}
}
return end;
}
}
C++实现
class Solution {
public:
int duplicateInArray(vector<int>& nums) {
int start = 1,end = nums.size()-1;
while(start < end){
int mid = (start + end)/2;
int count = 0;
for(auto x : nums){
if(x>=start && x<=mid){
count++;
}
}
if(count > mid - start +1){
end = mid;
}else{
start = mid+1;
}
}
return start;
}
};
C实现
int duplicateInArray(int *nums, int numsSize){
int start = 1;
int end = numsSize -1;
while(start<end){
int mid = (start+end)/2;
int count = 0;
for(int i=0;i<numsSize;i++){
if(nums[i] >= mid+1 && nums[i] <= end){
count++;
}
}
if(count > end - mid){
start = mid+1;
}else{
end = mid;
}
}
return start;
}
小记:
原题链接:不修改数组找出重复的数字
以上是关于AcWing15:不修改数组找出重复的数字的主要内容,如果未能解决你的问题,请参考以下文章