算法刷题笔记(CodeTop)

个人通过CodeTop的刷过一些经典算法

目录

leetcode 146 LRU缓存

leetcode 912 手撕快速排序

leetcode 15 三数之和

leetcode 53 最大子序和

leetcode 33 搜索旋转排序数组

leetcode 25 K个一组反转链表

leetcode 21 合并有序链表

leetcode 102 二叉树的层序遍历

leetcode 121 买卖股票的最佳时机

leetcode 141 环形链表

 leetcode 103 二叉树的锯齿形层序遍历

leetcode 20 有效的括号

leetcode 88 合并两个有序数组

leetcode 5 最长回文子串

leetcode 236 二叉树的最近公共祖先

leetcode 206 反转链表

leetcode 3 无重复字符的最长子串

leetcode 121 买卖股票的最佳时机

leetcode 1 两数之和

leetcode 200 岛屿数量

leetcode 46 全排列

leetcode 160 相交链表

leetcode 54 螺旋矩阵

leetcode 23 合并K个升序链表


leetcode 146 LRU缓存

思路:使用LinkedHashMap,LinkedHashMap是一个会按照put顺序,为key排序的的一个hash链表。作为缓存,在get时,如果命中缓存,将key删除重新put到链表尾部;在put时,如果命中缓存,将key删除再重新put到链表尾部,如果未命中且链表长度已满,删除链表头节点。即新的数据插入链表尾部,旧的数据从链表头部删除。

class LRUCache {
    private int capacity;
    private Map<Integer,Integer> map;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        map = new LinkedHashMap<>();
    }
    
    public int get(int key) {
        if(map.containsKey(key)){
            moveToFirst(key);
            return map.get(key);
        }else{
            return -1;
        }
    }
    
    public void put(int key, int value) {
        if(map.containsKey(key)){
            moveToFirst(key);
            map.put(key,value);
        }else{
            if(map.size() >= capacity){
                map.remove(map.keySet().iterator().next());
            }
            map.put(key,value);
        }
    }

    public void moveToFirst(int key){
        int val = map.remove(key);
        map.put(key,val);
    }
}

leetcode 912 手撕快速排序

思路:本题主要考察的是快排的写法,有两种,一种是基于交换的快排,一种是堆排序。

class Solution {

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

    public void quickSort(int[] nums,int L, int R){
        if(L >= R) return;
        int mid = (L + R) >> 1;
        swap(nums,L,mid);
        int pivot = nums[L];
        int index = L;
        for(int i = L+1; i <= R; i++){
            if(nums[i] < pivot){
                index++;
                swap(nums,index,i);
            }
        }
        swap(nums,L,index);
        quickSort(nums,L,index - 1);
        quickSort(nums,index + 1,R);    
    }

    public void swap(int[] nums,int i, int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

leetcode 15 三数之和

思路:本题的难点在于如何去除重复的解,本题解使用排序+双指针。

1.先对数组进行排序。

2.从数组开头遍历获取一个值,如果值大于0,直接结束;如果小于0,判断是否与前一个值相同,相同则循环找下一个值,直到不同。

3.确定一个数之后,再通过双指针获取剩下两个数,左指针指向当前的下一个数,右指针指向数组的最后一个数

4.将三个数相加,和大于0,右指针左移;和小于0,左指针右移;等于0,将三个数加入结果集,同时左指针右移、右指针左移,继续获取解。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> lists = new ArrayList<>();
        if(nums == null || nums.length < 3){
            return lists;
        }
        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 L = i + 1;
            int R = nums.length - 1;
            while( L < R ){
                if(L - 1 > i && nums[L-1] == nums[L]){
                    L++;
                    continue;
                }
                if(R + 1 < nums.length && nums[R+1] == nums[R]){
                    R--;
                    continue;
                }
                if(nums[i] + nums[L] + nums[R] == 0){
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[L]);
                    list.add(nums[R]);
                    lists.add(list);
                    L++;
                    R--;
                }else if(nums[i] + nums[L] + nums[R] > 0){
                    R--;
                }else{
                    L++;
                }
            }
        }
        return lists;
    }
}

leetcode 53 最大子序和

思路:最大子序和考虑到需要是连续的,当前元素加上之前的和如果大于当前元素本身,就加入的子序和中,如果当前元素加上之前的和小于当前元素本身,不如直接从当前元素开始重新计算子序和。

class Solution {
    public int maxSubArray(int[] nums) {
        int result = nums[0];
        int current = nums[0];
        for(int i = 1; i < nums.length; i++){
            if(current + nums[i] > nums[i]){
                current += nums[i];
            }else{
                current = nums[i];
            }
            result = Math.max(current,result);
        }
        return result;
    }
}

leetcode 33 搜索旋转排序数组

思路:使用二分查找,由于是将原本排序过的数组进行旋转,根据中点分成两段,两段之中一定有其中一段是有序的,所以这种情况也适用于二分查找。

二分不是单纯指从有序数组中快速找某个数,这只是二分查找的一个应用。

二分的本质是两段性,并非单调性。只要一段满足某个性质,另一段不满足某个性质,就可以使用二分。

class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while(left <= right){
            int mid = (left + right)  >> 1;
            if(nums[mid] == target) return mid;
            if(nums[0] <= nums[mid]){
                if(target < nums[mid] && target >= nums[left]){
                    right = mid - 1;
                }else{
                    left = mid + 1;
                }
            }else{
                if(target > nums[mid] && target <= nums[right]){
                    left = mid + 1;
                }else{
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
}

leetcode 25 K个一组反转链表

思路:本题考查的是翻转链表,不过是将整个链表拆分为n个分别进行翻转,同时还需要几个变量来记录翻转前后的节点。

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if (k == 1){
            return head;
        }
        ListNode dummy = new ListNode();
        dummy.next = head;
        ListNode pre = dummy;
        ListNode end = dummy;
        while (end.next != null) {
        for (int i = 0; i < k && end != null; i++) end = end.next;
        if (end == null) break;
        ListNode start = pre.next;
        ListNode next = end.next;
        end.next = null;
        pre.next = reverse(start);
        start.next = next;
        pre = start;
        end = pre;
        }
        return dummy.next;
    }

    public ListNode reverse(ListNode head){
        ListNode pre = null;
        ListNode current = hea
  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值