hot100(31-40)

  1. k个一组翻转链表
    与两个一组思路类似,只是我们每次需要判断之后是够有k个,每次需要记录k个中的第一个(新的尾),最后一个(新的头),最后一个的下一个(下次循环的开始),注意翻转链表要传结束位置。
java 复制代码
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy=new ListNode(0,head);
        ListNode p1=dummy;
        while(true){
            ListNode p2=p1.next,p3=p1.next;
            int count=0;
            while(count!=k&&p2!=null){
                p2=p2.next;
                count++;
            }
            if(count==k){
                ListNode newhead=reverse(p3,p2);
                p1.next=newhead;
                p3.next=p2;
                p1=p3;
            }else{
                break;
            }
        }
        return dummy.next;
    }
    public ListNode reverse(ListNode head,ListNode end){
        ListNode pre=null,last=head;
        while(last!=end){
            ListNode now=last;
            last=last.next;
            now.next=pre;
            pre=now;
        }
        return pre;
    }
}
  1. 随机链表的复制 三步走 织网(a-b-c a-a.-b-b.-c-c.)-连接(a...random=a...random.next)-结网
    注意几个点random可能会空,连接时需要判断,结网时需要判断后面是否还有
java 复制代码
class Solution {
    public Node copyRandomList(Node head) {
        if(head==null) return null;
        Node p1=head;
        while(p1!=null){
            Node node=new Node(p1.val);
            node.next=p1.next;
            node.random=p1.random;
            p1.next=node;
            p1=p1.next.next;
        }
        p1=head.next;
        while(p1!=null){
            if(p1.random!=null) p1.random=p1.random.next;
            if(p1.next!=null) p1=p1.next.next;
            else break;
        }
        Node newHead=head.next,p2=head;
        p1=head.next;
        while(p1!=null){
            p2.next=p2.next.next;
            p2=p2.next;
            if(p1.next!=null){
                p1.next=p1.next.next;
                p1=p1.next;
            }
            else break;
        }
        return newHead;
    }
}
  1. 排序链表
    自底向上,枚举step,对于每个step,遍历一遍链表,构造head1和head2,排序,连接
java 复制代码
class Solution {
    public ListNode sortList(ListNode head) {
        int len = 0;
        ListNode p1 = head, newHead = new ListNode(0, head);
        while (p1 != null) {
            p1 = p1.next;
            len++;
        }
        for (int i = 1; i < len; i <<= 1) {
            p1 = newHead;
            ListNode curr = p1.next;
            while (curr != null) {
                ListNode head1 = curr;
                for (int j = 1; j < i && curr != null; j++) {
                    curr = curr.next;
                }
                if (curr == null){
                    p1.next=head1;
                    break;
                }
                ListNode head2 = curr.next;
                curr.next = null;
                curr = head2;
                for (int j = 1; j < i && curr != null; j++) {
                    curr = curr.next;
                }
                ListNode next = null;
                if (curr != null) {
                    next = curr.next;
                    curr.next = null;
                }
                ListNode temp = merge(head1, head2);
                p1.next = temp;
                while (p1.next != null) {
                    p1 = p1.next;
                }
                curr=next;
            }
        }
        return newHead.next;
    }

    public ListNode merge(ListNode head1, ListNode head2) {
        ListNode dummy = new ListNode();
        ListNode p1 = dummy;
        while (head1 != null && head2 != null) {
            if (head1.val >= head2.val) {
                p1.next = head2;
                head2 = head2.next;
            } else {
                p1.next = head1;
                head1 = head1.next;
            }
            p1 = p1.next;
        }
        if (head1 != null)
            p1.next = head1;
        if (head2 != null)
            p1.next = head2;
        return dummy.next;
    }
}

递归 基本和归并排序一样(考试优先写,不容易错)

java 复制代码
class Solution {
    public ListNode sortList(ListNode head) {
        if(head==null) return head;
        if(head.next==null) return head;
        ListNode fast=head,slow=head;
        while(fast.next!=null&&fast.next.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        ListNode second=slow.next;
        slow.next=null;
        ListNode head1=sortList(head);
        ListNode head2=sortList(second);
        return merge(head1,head2);
    }
    public ListNode merge(ListNode head1,ListNode head2){
        ListNode dummy=new ListNode(),p1=dummy;
        while(head1!=null&&head2!=null){
            if(head1.val>=head2.val){
                p1.next=head2;
                head2=head2.next;
            }else{
                p1.next=head1;
                head1=head1.next;
            }
            p1=p1.next;
        }
        if(head1!=null) p1.next=head1;
        if(head2!=null) p1.next=head2;
        return dummy.next;
    }
}
  1. 合并K个升序链表
    分治排序,和上道题的思路基本一样
java 复制代码
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length==0) return null;
        return merge(lists,0,lists.length-1);
    }
    public ListNode merge(ListNode[] lists,int l,int r){
        if(l==r) return lists[l];
        int mid=(l+r)>>1;
        ListNode head1=merge(lists,l,mid);
        ListNode head2=merge(lists,mid+1,r);
        return mergeTwo(head1,head2);
    }
    public ListNode mergeTwo(ListNode head1,ListNode head2){
        ListNode dummy=new ListNode(),curr=dummy;
        while(head1!=null&&head2!=null){
            if(head1.val>head2.val){
                curr.next=head2;
                head2=head2.next;
            }else{
                curr.next=head1;
                head1=head1.next;
            }
            curr=curr.next;
        }
        if(head1!=null) curr.next=head1;
        if(head2!=null) curr.next=head2;
        return dummy.next;
    }
}
  1. LRU缓存
    加入虚拟头尾,方便增删
    get时,有的话要将节点放到前面
    put时,应该先判断是够存在,存在直接修改值,放到前面,不存在加入新元素,判断是否超过容量(是够删除元素)
java 复制代码
class LRUCache {

    private Node head;
    private Node tail;
    private Map<Integer, Node> map;
    private int capacity;
    private int count = 0;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        map = new HashMap<>();
        head = new Node();
        tail = new Node();
        head.next = tail;
        tail.pre = head;
        map.put(-1, head);
        map.put(-2, tail);
    }

    public int get(int key) {
        Node node = map.getOrDefault(key, null);
        if (node != null) {
            remove(node);
            addHead(node);
            return node.val;
        } else
            return -1;
    }

    public void put(int key, int value) {
        Node node = map.getOrDefault(key, null);
        if (node != null) {
            node.val=value;
            remove(node);
            addHead(node);
            return;
        }
        if (count == capacity) {
            map.remove(tail.pre.key);
            remove(tail.pre);
            count--;
        }
        node = new Node(key, value);
        addHead(node);
        map.put(key, node);
        count++;
    }

    public void remove(Node node) {
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    public void addHead(Node node) {
        Node next = head.next;
        node.pre = head;
        node.next = next;
        next.pre = node;
        head.next = node;
    }

    class Node {
        public int key;
        public int val;
        public Node pre;
        public Node next;

        public Node(int key, int val) {
            this.key = key;
            this.val = val;
        }

        public Node() {
        }
    }
}
  1. 二叉树中序遍历
    Morris 中序遍历思路:当前节点有左子树,我们将左子树最右节点连上当前节点,下次访问到这个节点,我们断开,并将当前结果加入res,继续遍历右子树
java 复制代码
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        while(root!=null){
            if(root.left!=null){
                TreeNode node=root.left;
                while(node.right!=null&&node.right!=root){
                    node=node.right;
                }
                if(node.right==null){
                    node.right=root;
                    root=root.left;
                }else{
                    node.right=null;
                    res.add(root.val);
                    root=root.right;
                }
            }
            else{
                res.add(root.val);
                root=root.right;
            }
        }
        return res;
    }
}
  1. 二叉树的最大深度
    递归
java 复制代码
class Solution {
    public int maxDepth(TreeNode root) {
        if(root==null) return 0;
        int left=maxDepth(root.left);
        int right=maxDepth(root.right);
        return Math.max(left+1,right+1);
    }
}
  1. 翻转二叉树
    递归
java 复制代码
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root==null) return null;
        TreeNode left=invertTree(root.left);
        TreeNode right=invertTree(root.right);
        root.left=right;
        root.right=left;
        return root;
    }
}
  1. 对称二叉树
    递归,比的是两个对应点的位置
java 复制代码
class Solution {
    public boolean isSymmetric(TreeNode root) {
        return symmetric(root.left, root.right);
    }

    public boolean symmetric(TreeNode left, TreeNode right) {
        if (left == null && right == null)
            return true;
        if (left != null && right != null) {
            boolean l = symmetric(left.left, right.right);
            boolean r = symmetric(left.right, right.left);
            return l && r && (left.val == right.val);
        }
        return false;
    }
}

迭代

注意用LinkedList(允许加入空值)ArrayDeque不允许空值

java 复制代码
class Solution {
    public boolean isSymmetric(TreeNode root) {
        Deque<TreeNode> q=new LinkedList<>();
        q.offer(root.left);
        q.offer(root.right);
        while(!q.isEmpty()){
           TreeNode node1=q.pollFirst();
           TreeNode node2=q.pollFirst();
           if(node1==null&&node2==null) continue;
           if(node1==null||node2==null||(node1.val!=node2.val)) return false; 
           q.offerLast(node1.left);
           q.offerLast(node2.right);

           q.offerLast(node1.right);
           q.offerLast(node2.left);
        }
        return true;
    }
}

二叉树直径

递归当前树的左右节点最大深度(有几个节点)

每次计算当前节点的最大直接,去更新全局最大直径

返回当前节点的最大深度

java 复制代码
class Solution {
    private int cnt=0;
    public int diameterOfBinaryTree(TreeNode root) {
        diameter(root);
        return cnt;
    }
    public int diameter(TreeNode node){
        if(node==null) return 0;
        int l=diameter(node.left);
        int r=diameter(node.right);
        cnt=Math.max(cnt,l+r);
        return Math.max(l,r)+1;
    }
}
相关推荐
xu_ws1 小时前
Spring-ai项目-deepseek-会话日志
java·人工智能·spring
咸蛋超超人1 小时前
下订单重复提交问题递进式解决方案案例
java·后端
lang201509282 小时前
20 Byte Buddy 深度解析:零依赖架构与高级参数注入艺术
java
Memory_荒年2 小时前
Java内存模型(JMM):别让你的代码在“马”路上翻车!
java·后端
Memory_荒年2 小时前
虚拟线程:让Java轻功水上漂,告别“线程体重焦虑”
java·后端
泡沫_cqy2 小时前
Java初学者文档
java·开发语言
gfdhy2 小时前
【Linux】服务器网络与安全核心配置|静态IP+SSH加固+防火墙,公网服务器必学实操
linux·服务器·网络·tcp/ip·算法·安全·哈希算法
是晴天呀。2 小时前
火山引擎接入项目
java·火山引擎