今日头条实习面试总结(2)

题目:

在一个长度为n的数组里的所有数字都在0到n-1的范围内。

数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。

请找出数组中任意一个重复的数字。

方法1:暴力嵌套两次循环,时间复杂度O(n^2),空间复杂度O(1)

bool weatherRepeat(vector<int> num){
    for(int i = 0; i < num.size(); ++i){
        for(int j = i + 1; j < num.size(); ++j){
            if(num[i] == num[j]){
				return true;
			}
		}
    }
    return false;
}

方法2:标记法,对出现过的数字使用一种数据结构存放其出现过的次数,如果超过一次返回true
时间复杂度O(n),空间复杂度O(n),可以使用map,也可以使用set,也可以用数组。关于map和set将在下一篇中具体来研究。这里使用一个vector<int> 来实现。

bool weatherRepeat(vector<int> num){
	vector<int> a(num.size(), 0);
	for(int i = 0; i < num.size(); ++i){
		a[num[i]]++;
		if(a[num[i]] == 2){
			return true;
		}
	}
	return false;
}

方法3:因为所有的数字都是在0 - n-1的范围内,所以在将数组排序之后,如果不存在重复的数字,则是按照0 - n-1依次递增的,所以利用这个特性,循环一次,如果num[i]与num[num[i]]的值相等,则返回true,不等则将num[i] 与 num[num[i]]的值进行交换。此方法的时间复杂度为O(n),空间复杂度为O(1)。

bool weatherRepeat(vector<int>& num){
	for(int i = 0; i < num.size(); ++i){
		if(num[i] != i){
			int temp = num[i];
			if(num[i] == num[temp]){
				return true;
			}else{
				int tp = num[i];
				num[i] = num[temp];
				num[temp] = tp;
			}
		}
	}
	return false;
}

在leetcode上有一道类似的题目

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements of [1, n] inclusive that do not appear in this array.

Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.

Example:

Input:
[4,3,2,7,8,2,3,1]

Output:
[5,6]


也是长度为n的数组a[n],其中值的范围都在 1-n之间,需要在O(n)的时间内找出数组中1-n之间未出现过的数字。

类似的思路,若m = a[i]的值正好覆盖 1-n, 则通过m访问a数组的值正好全部访问完,如果存在重复的值的话,

则会有访问不到的值,因此对于可以访问的值做标记,遍历一遍之后,遍历第二遍,如果未做标记,则其下标就是要求的值-1;

下面是相应的解答:


class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        vector<int> a;
        for(int i = 0; i < nums.size(); ++i){
            int m = abs(nums[i]) - 1;
            nums[m] = nums[m] > 0 ? -nums[m] : nums[m];
        }
        
        for(int i = 0; i < nums.size(); ++i){
            if(nums[i] > 0){
                a.push_back(i + 1);
            }
        }
        return a;
    }
};
用这个思路,也可以解答上面那个题,只不过时间复杂度更多点。O(2N)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值