恋上数据结构与算法第三季 高频题1

1._283_移动零

标签:数组、双指针

思路:如果扫描将0元素交换到数组尾部,会打乱顺序。所以应该将非零元素向前交换。

1)双指针,一个指针i用来扫描数组,一个指针cur指向可以交换的位置。

2)i指针指向0时,跳过,i++,但遇到非零元素时,交换i位置与cur位置的元素,并将i位置置为0,        cur++;

3)注意情况,cur与i相等时,cur++,i++

代码:

    public void moveZeroes(int[] nums) {
        for(int i = 0,cur = 0;i < nums.length;i++){
            if(nums[i] == 0) continue;
            if(cur != i){
                nums[cur] = nums[i];
                nums[i] = 0;
            }
            cur++;
        }
    }

2.两数之和

标签:数组、哈希表

思路:若存在扫描到后面,想利用O(1)时间看之前扫描过的元素是否存在某个值,可以用哈希             表,哈希表检查key是否存在时O(1)级别。

代码:

   public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = 0;i < nums.length;i++){
            Integer idx = map.get(target - nums[i]);
            if(idx != null){
                return new int[]{idx,i};
            }
            map.put(nums[i],i);
        }
        return null;

    }

3._15_三数之和

 

标签:数组、双指针、排序 

思路:

①暴力法 枚举每一个三元组 时间复杂度 O(n³) 空间O(1)

②优化:

先排序O(nlogn)

1)设置三个指针i,l,r, i 固定用来做扫描,l左指针,r右指针。

2)每一轮扫描,l = i + 1,r = nums.length - 1;当三个指针指向的元素的总和 < 0 时,l++;当偏大时r--,每一轮扫描的结束条件时 l >= r;

3)去重:当下一个i 指向的元素与此前的 i 指向元素相同时,跳过。当 l + 1指向的和 l 指向的相同时,跳过,直接l++,当 r - 1指向的和 r 指向的相同时,跳过,直接 r--.

代码:

    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> list = new ArrayList<>();
        if (nums == null) return list;
        if (nums.length < 3) {
            return list;
        }
        Arrays.sort(nums);
        for (int i = 0; i <= nums.length - 3; i++) {
            if (nums[i] == nums[i - 1]) continue;
            int target = -nums[i];
            int l = i + 1;
            int r = nums.length - 1;
            while (l < r) {
                if (nums[l] + nums[r] == target) {
                    list.add(Arrays.asList(nums[i], nums[l], nums[r]));
//                    去重
                    while(l < r && nums[l] == nums[l + 1]) l++;
                    while(l < r && nums[r] == nums[r - 1]) r--;
//                    往中间逼近
                    l++;
                    r--;
                } else if (nums[l] + nums[r] < target) { //结果偏小
                    l++;
                } else {
                    r--;
                }
            }
        }
        return list;
    }

4._50_Pow(x,n)

标签:递归、数学、快速幂

思想:① 将n个x进行相乘 时间(n) 空间O(n)

          ② 快速幂

1)递归

代码:

    public double myPow1(double x, int n) {
        if(n == 1) return 0;
        if(n == -1) return 1 / x;
//        是否为奇数
        boolean odd = (n & 1) == 1;

        double half = myPow(x,n >> 1);
        half *= half;

        return odd ? half*x :half;

    }

时间复杂度 O(logn) 空间复杂度O(logn)

2)快速幂+非递归

 代码:

   public double myPow(double x, int n) {
        double res = 1.0;
        boolean neg = n < 0;
        long y = neg ? -((long)n) : n;

        while(y > 0){
            boolean odd = (y & 1) == 1;
//            如果最后一个二进制位是1,就雷澄上x
            if(odd){
                res *= x;
            }
            x *= x;
//            舍弃掉最后一个二进制位
            y >>= 1;
        }
        return neg ? (1 / res) : res;

    }

时间复杂度:O(logn) 空间复杂度:O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值