leetcode05

155. 最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:
MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin()获取堆栈中的最小元素。

使用辅助栈的解法,空间复杂度 O ( n ) O(n) O(n)

class MinStack {
    Stack<Integer> vals;
    Stack<Integer> minVals;
    public MinStack() {
        vals = new Stack();
        minVals = new Stack();
    }
    public void push(int val) {
        vals.push(val);
        if(minVals.isEmpty())  minVals.push(val);
        else  minVals.push(Math.min(val, minVals.peek()));
    }
    public void pop() {
        minVals.pop();
        vals.pop();
    }
    public int top() {
        return vals.peek();
    }
    public int getMin() {
        return minVals.peek();
    }
}

不使用辅助栈的方法,空间复杂度 O ( 1 ) O(1) O(1)

class MinStack {
    Stack<Long> diffs;
    long minVal;
    public MinStack() {
        diffs = new Stack();
    }
    public void push(int val) {
        if(diffs.isEmpty()){
            diffs.push(0L);
            minVal = val;
        }else{
            diffs.push((long)val - minVal);
            minVal = Math.min(minVal, val);
        }
    }
    public void pop() {
        Long temp = diffs.pop();
        if(temp < 0)  minVal -= temp;
    }
    public int top() {//top是不能出栈的
        System.out.println(diffs.peek());
        return (int)(minVal + Math.max(diffs.peek(), 0));
    }
    public int getMin() {
        return (int)minVal;
    }
}

148.排序链表

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表。

进阶:

你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

示例 1:

image

输入:head = [4,2,1,3]
输出:[1,2,3,4]

递归归并

class Solution {
    public ListNode sortList(ListNode head) {
        ListNode dummy = new ListNode(-1, head);
        // 获取链表的长度
        int len = 0;
        ListNode curr = head;
        while (curr!=null) {
            len++;
            curr = curr.next;
        }

        // 循环遍历
        // 外层遍历step 内层处理每step个元素进行一次merge
        for (int step=1; step<len; step*=2) {
            ListNode tail = dummy;
            curr = dummy.next;
            while (curr!=null) {
                ListNode left = curr;
                ListNode right = cut(left, step);
                curr = cut(right, step);
                tail.next = merge(left, right);
                while (tail.next!=null) {
                    tail = tail.next;
                }
            }
        }
    return dummy.next;
    }

    // 将链表从from开始切掉前step个元素,返回后一个元素
    public ListNode cut(ListNode from, int step) {
        step--;
        while (from!=null && step>0) {
            from = from.next;
            step--;
        }
        if (from==null) {
            return null;
        } else {
            ListNode next = from.next;
            from.next = null;
            return next;
        }
    }

    // 将两个有序链表合并成一个,返回合并后的头节点
    public ListNode merge(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode();
        ListNode curr = dummy;
        while (l1!=null && l2!=null) {
            if (l1.val<l2.val) {
                curr.next = l1;
                l1 = l1.next;
            } else {
                curr.next = l2;
                l2 = l2.next;
            }
            curr = curr.next;
        }
        if (l1!=null) {
            curr.next = l1;
        }
        if (l2!=null) {
            curr.next = l2;
        }
        return dummy.next;
    }
}

快速排序

class Solution {
    public ListNode sortList(ListNode head) {
        return quickSort(head);
    }

    public ListNode quickSort(ListNode head) {
        if (head==null || head.next==null) {
            return head;
        }
        ListNode h1 = new ListNode();
        ListNode h2 = new ListNode();
        ListNode h3 = new ListNode();
        ListNode t1 = h1;
        ListNode t2 = h2;
        ListNode t3 = h3;
        ListNode curr = head;
        int pivot = getMid(head).val;  // 用中间节点的原因是,如果每次用最左边的结点,对于纯递增和纯递减的case就退化为O(n)

        while (curr!=null) {
            ListNode next = curr.next;
            if (curr.val < pivot) {
                curr.next = null;
                t1.next = curr;
                t1 = t1.next;
            } else if (curr.val == pivot) {
                curr.next = null;
                t2.next = curr;
                t2 = t2.next;
            } else {
                curr.next = null;
                t3.next = curr;
                t3 = t3.next;
            }
            curr = next;
        }

        // < 的链表和 > 的链表分别快排
        h1 = quickSort(h1.next);
        h3 = quickSort(h3.next);

        // h1链表不一定有元素 h2链表一定有元素 先把h2、h3连起来
        h2 = h2.next;
        t2.next = h3;
        // 如果h1链表为空 直接返回h2即可
        // 否则找到h1链表的结尾,连上h2的头
        if (h1==null) {
            return h2;
        } else {
            t1 = h1;
            // 找到t1链表的结尾
            while (t1.next!=null) {
                t1 = t1.next;
            }
            t1.next = h2;
            return h1;
        }
    }

    public ListNode getMid(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast!=null && fast.next!=null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }

}

105.从前序与中序遍历序列构造二叉树

class Solution {
    private HashMap<Integer,Integer> hash = new HashMap<>();
    
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int n = preorder.length;
        for(int i = 0;i < n;i++){
            hash.put(inorder[i],i);
        }
        return MybuildTree(preorder, 0, n - 1, inorder, 0 , n-1);
    }

    public TreeNode MybuildTree(int[] preorder,int pl,int pr,int[] inorder,int il,int ir){
        if(pl > pr){
            return null;
        }
        int pre_root = pl;
        int in_root = hash.get(preorder[pre_root]);
        TreeNode root = new TreeNode(preorder[pre_root]);
        int size_left = in_root - il;
        root.left = MybuildTree(preorder, pl + 1, pl + size_left, inorder, il, ir - 1);
        root.right = MybuildTree(preorder, pl + size_left + 1, pr, inorder, in_root + 1, ir);
        return root;
    }
}

106.从中序与后序遍历序列构造二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 * int val;
 * TreeNode left;
 * TreeNode right;
 * TreeNode() {}
 * TreeNode(int val) { this.val = val; }
 * TreeNode(int val, TreeNode left, TreeNode right) {
 * this.val = val;
 * this.left = left;
 * this.right = right;
 * }
 * }
 */
class Solution {
    Map<Integer, Integer> map = new HashMap<>();

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        int n = postorder.length;
        for (int i = 0; i < n; i++) {
            map.put(inorder[i], i);
        }
        return myBuildTree(inorder, 0, n - 1, postorder, 0, n - 1);
    }

    public TreeNode myBuildTree(int[] inorder, int inLeft, int inRight, int[] postorder, int postLeft, int postRight) {
        if (postLeft > postRight) {
            return null;
        }
        TreeNode node = new TreeNode(postorder[postRight]);
        int inorderIndex = map.get(postorder[postRight]);
        int leftSize = inorderIndex - inLeft;
        node.left = myBuildTree(inorder, inLeft, inorderIndex - 1, postorder, postLeft, postLeft + leftSize - 1);
        node.right = myBuildTree(inorder, inorderIndex + 1, inRight, postorder, postLeft + leftSize, postRight - 1);
        return node;
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值