当前位置: 首页 > article >正文

hot100-141、142、148、146、136、169、75、31、287

链表 

141. 环形链表(简单)
 

方法一、快慢指针

有环总会相遇

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode a = head,b = head;
        if(head == null)return false;
        do{
            a = a.next;
            b = b.next;
            if(b!=null)b = b.next;
        }while(a!=b && b != null);
        return b != null;
    }
}

方法二、哈希

环的特性是单指针遍历可以去看已经看过的节点

public class Solution {
    public boolean hasCycle(ListNode head) {
        Set<ListNode> seen = new HashSet<ListNode>();
        while (head != null) {
            if (!seen.add(head)) {
                return true;
            }
            head = head.next;
        }
        return false;
    }
}

作者:力扣官方题解
链接:https://leetcode.cn/problems/linked-list-cycle/solutions/440042/huan-xing-lian-biao-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

方法三、暴力

无环长度最多1w,所以遍历1w+次看看 

public class Solution {
    public boolean hasCycle(ListNode head) {
       ListNode left = head;
       int count = 0;
       if(left == null){
        return false;
       }
       while(left.next != null){
            count++;
            left = left.next;
            if(count > 10000){
                return true;
            }
        }
        return false; 
    }
}

142. 环形链表 II(中等)


 

方法一、快慢指针

先相遇,让b回原点,ab同时步长为1走


public class Solution {
    public ListNode detectCycle(ListNode head) {
                ListNode a = head,b = head;
                if(head == null)return null;
                do{
                    a = a.next;
                    b = b.next;
                    if(b!=null)b = b.next;
                }while(a!=b && b != null);
                if(b == null)return null;
                b = head;
                while(a != b){
                    a = a.next;
                    b = b.next;
                }
                return b;
    }
}

148. 排序链表(中等)

方法一、归并排序

此处findMid函数我有踩坑,才注意到fast指向next,然后需要判断next是不是空,因为数分奇偶,可能触发边界条件。重新学了一下merge的方式。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode sortList(ListNode head) {
        if(head == null || head.next == null)return head;
        ListNode mid = findMiddle(head);
        ListNode rHead = mid.next;
        mid.next = null;
        ListNode left =  sortList(head);
        ListNode right =  sortList(rHead);
        return mergeList(left,right);
    }
    public ListNode findMiddle(ListNode head){
        if(head == null)return null;
        ListNode slow = head,fast = head.next;
        while(fast != null && fast.next!= null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    public ListNode mergeList(ListNode l1, ListNode l2){
        ListNode dummy = new ListNode(-1),temp = dummy;
        while(l1 != null && l2 != null){
            if(l1.val > l2.val){
                temp.next = l2;
                l2 = l2.next;
            }else{
                temp.next = l1;
                l1 = l1.next;
            }
            temp = temp.next;
        }
        if (l1!=null){
            temp.next = l1;
        }
        if (l2!=null){
            temp.next = l2;
        }
        return dummy.next;
    }
}

 
146. LRU 缓存(中等)

方法一、双向链表+哈希

涉及顺序则试试链表,涉及O(1)哈希,双向队列不能把中间的移到后面。其实还可以再函数模块化一点但是懒得了,代码结构不好看。

class LRUCache {
    private class Node{
        int key,value;
        Node prev,next;
        Node(int k,int v){
            key = k;
            value = v;
        }
    }
    private int capacity;
    private int count;
    private Node dummy = new Node(-1,-1);
    private HashMap<Integer,Node> keyToNode = new HashMap<>();
    public LRUCache(int capacity) {
        this.capacity = capacity;
        dummy.prev = dummy;
        dummy.next = dummy;
    }

    public int get(int key) {
        Node temp = keyToNode.get(key);
        if(temp == null)return -1;
        //拿走
        temp.prev.next = temp.next;
        temp.next.prev = temp.prev;
        //放入
        temp.next = dummy.next;
        dummy.next.prev = temp;
        temp.prev = dummy;
        dummy.next = temp;
        return temp.value;
    }

    public void put(int key, int value) {
        Node temp = keyToNode.get(key);
        if(temp == null){
            count++;
            Node temp1 = new Node(key,value);
            temp1.next = dummy.next;
            dummy.next.prev = temp1;
            temp1.prev = dummy;
            dummy.next = temp1;
            keyToNode.put(key,temp1);
        }else{
            temp.value = value;
            get(key);
        }
        if(capacity < count){
            count--;
            keyToNode.remove(dummy.prev.key);
            dummy.prev.prev.next = dummy;
            dummy.prev = dummy.prev.prev;
        }
    }
}

技巧

136. 只出现一次的数字(简单)

方法一、异或

class Solution {
    public int singleNumber(int[] nums) {
        int n = nums.length,res = 0;
        for(int i = 0;i < n;i++){
            res^=nums[i];
        }
        return res;
    }
}

 
169. 多数元素(简单)

进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。 

方法一、栈

class Solution {
    public int majorityElement(int[] nums) {
       int n = nums.length;
       if(n == 1)return nums[0]; 
       Deque<Integer> st = new ArrayDeque<>();
       for(int i = 0;i < n;i++){
        if(st.isEmpty() || st.peek() == nums[i]){
            st.push(nums[i]);
        }else{
            st.pop();
        }
       }
       return st.peek();
    }
}

 

 方法二、摩尔投票

常数相消归零改换 本质上是不需要记录过去的数字本身 只需计数 所以栈信息量溢出

class Solution {
    public int majorityElement(int[] nums) {
       int n = nums.length,res = nums[0],cnt = 1;
       for(int i = 1;i < n;i++){
        if(res == nums[i]){
            cnt++;
        }else if(--cnt == 0){
            res = nums[i];
            cnt++;
        }
       }
       return res;
    }
}

75. 颜色分类(中等)

方法一、双指针

也可以遍历一次统计数量覆盖改写

class Solution {
    public void sortColors(int[] nums) {
        int n = nums.length;
        int x = 0,y = 0;
        for(int i = 0;i < n;i++){
            int t = nums[i];
            nums[i] = 2;
            if(t < 2)nums[x++] = 1;
            if(t < 1)nums[y++] = 0;
        }
        
    }
}

31. 下一个排列(中等)

 

 方法一、两次循环

最初错误思路只考虑到交换但没有反序

倒序遍历,找到第一个降点index1,第二次遍历,找到(index1,n)中第一个大于index1的点index2。交换两位,将(index1,n)倒序。

相对代码而言,index1最初定位0,最后swap功能可以合并。不改善性能,但可以优化逻辑

class Solution {
    public void nextPermutation(int[] nums) {
        int n = nums.length,index1 = -1,index2 = 0;
        if(n == 1)return;
        for(int i = n-2;i >=0;i--){
            if(nums[i] < nums[i+1]){
                index1 = i;
                break;
            }
        }
        if(index1 == -1){
            reverse(nums,0,n-1);
            return;
        }
        for(int i = n-1;i > index1;i--){
            if(nums[index1] < nums[i]){
                index2 = i;
                break;
            }
        }
        swap(nums,index1,index2);
        reverse(nums,index1+1,n-1);
        
    }
    public void reverse(int[] nums,int x,int y){
        for(int i = x,j = y;i<j;i++,j--){
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
    }
    public void swap (int[] nums,int i,int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

287. 寻找重复数(中等)

方法一、拟成环链表 

数组中的下标和数字构成一个指向

class Solution {
    public int findDuplicate(int[] nums) {
        int n = nums.length,slow = 0,fast = 0;
            slow = nums[slow];
            fast = nums[nums[fast]];
        while(slow != fast){//这题必然有环
            slow = nums[slow];
            fast = nums[nums[fast]];
        }
        fast = 0;
        while(slow != fast){
            slow = nums[slow];
            fast = nums[nums[fast]];
        }
        return nums[slow];
    }
}


http://www.kler.cn/a/554719.html

相关文章:

  • 基于用户分组的活动运营策略与“开源AI智能名片2+1链动模式S2B2C商城小程序”的应用探索
  • vue登陆下拉菜单
  • Unreal5从入门到精通之在编辑器中更新 UserWidgets
  • 用openresty和lua实现壁纸投票功能
  • sql server 从库创建的用户名登录后访问提示数据库无权限
  • 高等数学(上)题型笔记(六)定积分的应用
  • CentOS创建软链接(符号链接)、硬链接和区别
  • 黑盒测试和白盒测试常用的测试方法有哪些?
  • Quasar:轻量级、高效的.NET远程管理工具
  • 自动化办公|通过xlwings进行excel格式设置
  • 解决webpack5.54打包图片及图标的问题
  • Nginx 安装及配置教程(Windows)【安装】
  • 娱乐使用,可以生成转账、图片、聊天等对话内容
  • Webhook同步数据
  • 请解释一下Standford Alpaca格式、sharegpt数据格式-------deepseek问答记录
  • 详细介绍下软件生命周期的各个阶段以及常见的软件生命周期模型
  • MySQL基础回顾#1
  • AI 为金融领域带来了什么突破?
  • 若依-@Excel新增注解numberFormat
  • Kubernetes的Ingress 资源是什么?