50、数组中重复元素
哈希表——set——遍历数组 o(n) o(n)
class Solution {
public int findRepeatNumber(int[] nums) {
Set<Integer> set = new HashSet<Integer>();
int repeat = -1;
for (int num : nums) {
if (set.add(num)==false) {//重复数字添加不进set,返回null值
repeat = num;
break;
}
}
return repeat;
}
}
如果没有重复数字,那么正常排序后,数字i应该在下标为i的位置,所以思路是重头扫描数组,遇到下标为i的数字如果不是i的话,(假设为m),那么我们就拿与下标m的数字交换。在交换过程中,如果有重复的数字发生,那么终止返回ture
class Solution {
public int findRepeatNumber(int[] nums) {
int temp;
for(int i=0;i<nums.length;i++){
while (nums[i]!=i){
if(nums[i]==nums[nums[i]]){
return nums[i];
}
temp=nums[i];
nums[i]=nums[temp];
nums[temp]=temp;
}
}
return -1;
}
}
Python3
方法一: 先排序,然后看相邻元素是否有相同的,有直接return。 不过很慢,时间O(nlogn)了,空间O(1)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
nums.sort()
pre = nums[0]
n = len(nums)
for index in range(1, n):
if pre == nums[index]:
return pre
pre = nums[index]
方法二:哈希表 时间O(n),空间O(n)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
repeatDict = {}
for num in nums:
if num not in repeatDict:
repeatDict[num] = 1
else:
return num
方法三:时间复杂度O(n),空间复杂度O(1)。可以看做是一种原地哈希,不过没有用到字典。具体做法就是因为题目中给的元素是 < len(nums)的,所以我们可以让 位置i 的地方放元素i。如果位置i的元素不是i的话,那么我们就把i元素的位置放到它应该在的位置,即 nums[i] 和nums[nums[i]]的元素交换,这样就把原来在nums[i]的元素正确归位了。如果发现 要把 nums[i]正确归位的时候,发现nums[i](这个nums[i]是下标)那个位置上的元素和要归位的元素已经一样了,说明就重复了,重复了就return
class Solution:
def findRepeatNumber(self, nums) -> int:
n = len(nums)
for i in range(n):
while i != nums[i]:
if nums[i] == nums[nums[i]]:
return nums[i]
temp = nums[i]
nums[i], nums[temp] = nums[temp], nums[i]
# 注意这里不要写成nums[i], nums[nums[i]] = nums[nums[i]], nums[i]
# 这种嵌套的直接交换在python里面得到的不是你想要的。提交了好几次发现之间在里面死循环了,debug了一下才
1、二维数组中的查找
有序的数组很显然应该想到二分。
public class Solution {
public boolean Find(int target, int [][] array) {
int i = array.length - 1, j = 0;//从最下面一行左边 开始扫描
while(i >= 0 && j < array[0].length)//如果扫描到最上面一行右边 停止
{
if(array[i][j] > target) i--; // 比目标值大,整行都不行
else if(array[i][j] < target) j++;// 比目标值小,整列都不行
else return true;
}
return false;
}
}
13、调整数组顺序使奇数位于偶数前面
如果没有要求相对位置不变的话,可以采用双端指针
双端指针,会改变相对位置
不维持原来的先后顺序就左右指针
public class Solution {
public int[] reOrderArray (int[] array) {
int i = 0, j = array.length - 1, tmp;
while(i < j) {
while(i < j && (array[i] & 1) == 1) i++;//i是奇数
while(i < j && (array[j] & 1) == 0) j--;//j是偶数
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
return array;
}
}
class Solution:
def reOrderArray(self , array ):
# write code here
if not array:
return []
for passnum in range(len(array)-1, 0, -1):
for i in range(passnum):
if array[i] % 2 == 0 and array[i+1] % 2 != 0:
array[i], array[i+1] = array[i+1], array[i]
return array
要维持原来的顺序可以借鉴冒泡排序,将相邻的偶数和奇数交换。
import java.util.*;
public class Solution {
public int[] reOrderArray (int[] array) {
// bubble sort 冒泡排序
if (array == null || array.length == 0) return new int[0];
int n = array.length;
boolean changed = true;
for (int i=n-1; i>0 && changed; i--) {
changed = false;
for (int j=0; j<i; ++j) {
// 左边是偶数, 右边是奇数的情况
if ((array[j] & 1) == 0 && (array[j+1] & 1) == 1) {
changed = true;
int tmp = array[j];
array[j] = array[j+1];
array[j+1] = tmp;
}
}
}
return array;
}
}
暴力做法
先找出奇数利用2余某个数不为零就是奇数(这里不考虑0的情况),那么余2是0那就是偶数啦
2、然后奇数放在一个链表里面,偶数放在一个链表里面。链表不需要事先知道长度大小,所以用链表方便,数组是没法确定大小的。
3、就先将放了奇数的链表一个一个出栈(poll函数)放在题目给的array中,然后就是偶数,思路中的很简单
public class Solution {
public int[] reOrderArray (int[] array) {
// write code here
if(array.length == 0){
return array;
}
Queue<Integer> jishu = new LinkedList<>();//Queue是单独的队列
Queue<Integer> oushu = new LinkedList<>();//Dueue是双端队列
for(int i = 0;i < array.length ;i++){
if(array[i] % 2 != 0){
jishu.add(array[i]);
}else{
oushu.add(array[i]);
}
}
for(int i = 0;i < array.length ;i++){
if(!jishu.isEmpty()){
array[i] = jishu.poll();
}else{
array[i] = oushu.poll();
}
}
return array;
}
}
40、数组中只出现过一次的数字
牛客网没有指定时空复杂度,用哈希表可以方便实现
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param array int整型一维数组
* @return int整型一维数组
*/
public int[] FindNumsAppearOnce (int[] array) {
Map<Integer,Integer> dic = new HashMap<>();
for(int i = 0;i < array.length;i++){
dic.put(array[i],dic.getOrDefault(array[i],0) + 1);
*这里使让array[i]如果已经存在,value就是1,否则默认为0
}
int[] arr = new int[2];
int k=0;
for(int i=0;i<array.length;i++){
if(dic.get(array[i]) == 1)
arr[k++] = array[i];
}
Arrays.sort(arr);
return arr;
}
}
如果指定复杂度:要求时间复杂度为O(n),空间复杂度为O(1)
不需要额外空间的方法,就往位运算上想
异或
交换律:a ^ b ^ c <=> a ^ c ^ b
任何数于0异或为任何数 0 ^ n => n
相同的数异或为0: n ^ n => 0
var a = [2,3,2,4,4]
2 ^ 3 ^ 2 ^ 4 ^ 4等价于 2 ^ 2 ^ 4 ^ 4 ^ 3 => 0 ^ 0 ^3 => 3