leetcode刷题计划Day3

1. 两数之和【简单】

https://leetcode-cn.com/problems/two-sum/

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> hashmap = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (hashmap.containsKey(target - nums[i])) {
                return new int[]{ hashmap.get(target - nums[i]), i };
            }
            else {
                hashmap.put(nums[i], i);
            }
        }
        return null;
    }
}
215.数组中的第K个最大元素【中等】

https://leetcode-cn.com/problems/kth-largest-element-in-an-array/
这道题主要就是考察排序算法,我们可以用快速排序堆排序两种方法。这两种基础排序算法一定要掌握。

利用快速排序思想:
因为经过一轮快速排序中的partition,我们能够让某一个值放到他应该在的位置,如下面例子中的 “6” , 它通过将小于它的值都放到它前面,大于它的值放到它后面,来确定了自己的位置(虽然前后的值的顺序是乱序的,但是不重要)。所以我们可以通过partition后这个值的index,来确定是不是target(第K大的元素)。如果不是,根据他的index与target的大小比较,我们可以缩小操作范围,从而节省时间。如: 我们此时把数字6的位置确定了,他在 index = 4 的位置,而假如要找倒数第一大的话,我们就需要找 index = nums.length - 1(本例中为7)位置的数。4 < 7,因此我们从6的后面开始找即可,而不用考虑6前面的数了。
在这里插入图片描述

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int len = nums.length;
        int target = len - k;
        int left = 0, right = len - 1;
        while (true) {
            int index = partition(nums, left, right);
            if (index == target)
                return nums[target];
            else if (index < target)
                left = index + 1;
            else if (index > target)
                right = index - 1;
        }
    }

    private int partition (int[] nums, int left, int right) {
        int pivot = nums[left]; // 定义轴值
        int j = left;
        for (int i = left + 1; i <= right; i++) { // 只需要从(left, right]之间找target就行了
            if (nums[i] < pivot) {
                j++;
                swap (nums, j, i); // 将[left+1,right]的值分好,left是本次的轴值
            }
        }
        swap(nums, j, left);// 把left插到对应位置
        return j;
    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }

}

利用小根堆思想:

15. 三数之和【中等】

https://leetcode-cn.com/problems/3sum/
排序 + 双指针,对 sum 及 left、right 指针指向的数分治

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums == null || nums.length < 3)
            return res;
        Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > 0)
                break;
            if (i > 0 && nums[i] == nums[i-1])
                continue;
            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                if (sum == 0) {
                    res.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    while (left < right && nums[left+1] == nums[left]) left++;
                    while (left < right && nums[right - 1] == nums[right]) right--;
                    left ++;
                    right --;
                }
                else if (sum < 0) left++;
                else if (sum > 0) right--;
            }
        }
        return res;
    }
}
912. 排序数组(请至少尝试2种及以上的排序算法)【中等】

https://leetcode-cn.com/problems/sort-an-array/
推排序

class Solution {
    public int[] sortArray(int[] nums) {

        int len = nums.length;
        int[] a = new int[len + 1];

        for (int i = 0; i < nums.length; ++i) {
            a[i+1] = nums[i];
        }          
        //下沉建堆
        for (int i = len/2; i >= 1; --i) {
            sink(a,i,len);
        }

        int k = len;
        //排序
        while (k > 1) {
            swap(a,1,k--);
            sink(a,1,k);
        }
        for (int i = 1; i < len+1; ++i) {
            nums[i-1] = a[i];
        }
        return nums;
    }
    public void sink (int[] nums, int k,int end) {
        //下沉
        while (2 * k <= end) {
            int j = 2 * k;
            //找出子节点中最大或最小的那个
            if (j + 1 <= end && nums[j + 1] > nums[j]) {
                j++;
            }
            if (nums[j] > nums[k]) {
                swap(nums, j, k);
            } else {
                break;
            }
            k = j;
        }
    }
    public void swap (int nums[], int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
    
}

快速排序

class Solution {
    public int[] sortArray (int[] nums) {   
        
        quickSort(nums,0,nums.length-1);
        return nums;
        
    }

    public void quickSort (int[] nums, int low, int high) {

        if (low < high) {
            int index = partition(nums,low,high);
            quickSort(nums,low,index-1);
            quickSort(nums,index+1,high);
        } 
        
    }

    public int partition (int[] nums, int low, int high) {
            
            int pivot = nums[low];
            int start = low;
        
            while (low < high) {
                while (low < high && nums[high] >= pivot) high--;           
                while (low < high && nums[low] <= pivot) low++;
                if (low >= high) break;
                swap(nums, low, high);  
            }
            //基准值归位
            swap(nums,start,low);
            return low;
    }  
    public void swap (int[] nums, int i, int j) {      
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
     } 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值