数组——50、1、13、40

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值