【Leetcode热题】打卡 day11——20(更新至14)

目录

1、合并两个有序链表 - 链表 + 暴力 / 递归

(1)暴力

(2)递归

2、括号生成 - dfs + 剪枝

3、合并K个升序链表 - 暴力合并两个链表升级版 / 最小堆(优先队列)

(1)暴力 - 合并两链表升级版

(2)最小堆(优先队列)

4、下一个排列 - 思维+排序


1、合并两个有序链表 - 链表 + 暴力 / 递归

21. 合并两个有序链表

【Leetcode热题】打卡 day11——20(更新至14)_第1张图片

(1)暴力

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    ListNode dummy=new ListNode();
    ListNode cur=dummy;
    
    while(l1!=null&&l2!=null)
    {
        if(l1.val<=l2.val)
        {
            cur.next=l1;
            l1=l1.next;
        }else{
            cur.next=l2;
            l2=l2.next;
        }
        cur=cur.next;
    }
    cur.next= l1==null? l2:l1;
    return dummy.next;
    }
}

(2)递归

思路:

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

【Leetcode热题】打卡 day11——20(更新至14)_第2张图片

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        
        if(l1==NULL) return l2;
        if(l2==NULL) return l1;
        
        if(l1->val<=l2->val) 
        {
            l1->next=mergeTwoLists(l1->next,l2);
            return l1;
        }
        else {
            l2->next=mergeTwoLists(l1,l2->next);
            return l2;
        } 
    }
};

2、括号生成 - dfs + 剪枝

22. 括号生成

【Leetcode热题】打卡 day11——20(更新至14)_第3张图片

【Leetcode热题】打卡 day11——20(更新至14)_第4张图片

先求所有括号组合情况,我们发现可以用dfs列出(画出dfs树)

然后我们发现可以进行剪枝:

  • 当左括号数>n时,像 (()( 、((()这种肯定不行
  • 当dfs过程中右括号数>左括号数时,再深入括号也定然不匹配(先左括号再右括号才能组成完整的)

排除上述两种情况,则剩下的就是匹配的括号情况

class Solution {
public:
    vector res;
    vector generateParenthesis(int n) {
        string str;
        dfs("",0,0,n);
        return res;
    }

    void dfs(string cur,int left,int right,int n)
    {
        if(left > n || left < right) return; // 如果左括号超了,或右括号比左括号多,该分支肯定不行

        if(cur.size() == n*2)
        {
            res.push_back(cur);
            return;
        }
        
        dfs(cur+"(",left+1,right,n);

        dfs(cur+")",left,right+1,n);
    }
};

3、合并K个升序链表 - 暴力合并两个链表升级版 / 最小堆(优先队列)

23. 合并 K 个升序链表

【Leetcode热题】打卡 day11——20(更新至14)_第5张图片

(1)暴力 - 合并两链表升级版

思路:

把K个链表合并转换为每次合并两个链表 


class Solution {
    
    public ListNode mergeKLists(ListNode[] lists) {
    int n=lists.length;
    ListNode res=null;
    for(int i=0;i

(2)最小堆(优先队列)

思路:

最小堆性质是:每次取出的堆顶元素都保证是最小值

我们可以利用这个性质,先把所有链表的头结点存进最小堆中

然后不断取堆顶元素,并存入取出元素的下一个元素

循环取出堆顶直至堆空,也就成功获取一条从小到大的顺序链表

// c++
class Solution {
public:
    ListNode* mergeKLists(vector& lists) {
        auto cmp=[](ListNode* a,ListNode* b) {return a->val > b->val;};
        priority_queue,decltype(cmp)> pq;

        for(ListNode* x:lists)
            if(x) pq.push(x);

        ListNode* dummy=new ListNode();
        ListNode* cur=dummy;

        while(!pq.empty())
        {
            ListNode* t=pq.top();
            pq.pop();
            if(t->next) pq.push(t->next);
            cur->next=t;
            cur=cur->next;
        }
        return dummy->next;
    }
};
// java
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        PriorityQueue pq = new PriorityQueue<>((a, b) -> a.val - b.val);
        for (ListNode head : lists) 
            if (head != null) pq.offer(head);
        
        ListNode dummy = new ListNode();
        ListNode cur = dummy;
        while (!pq.isEmpty()) 
        {
            ListNode node = pq.poll();
            if (node.next != null) pq.offer(node.next);
            
            cur.next = node;
            cur = cur.next;
        }
        return dummy.next;
    }
}

4、下一个排列 - 思维+排序

【Leetcode热题】打卡 day11——20(更新至14)_第6张图片

思路:

题目要求寻找比当前序列大,且最接近当前序列值的新序列,即就是求向左逼近该数的新数

为了保证新序列在比原序列大的情况下尽可能小,所以我们从后向前寻找一个大值与前面进行交换(从后向前是因为尽量改变低位的值以保证值最小)

怎么寻找交换的位置呢?其实应该从后向前找第一个升序对(i,j),因为只有升序交换后,值才可能变大

解决了值变大的问题,再而要控制数尽可能小。也就是在交换位置之后寻找一个比交换位置的数大的最小数,与之交换

从后向前找第一个升序对(i,j),所以说 [j,end] 区间必定是降序的,记录i的下标为k。

在[j,end]区间内从后向前找第一个比nums[k]大的数,交换它与nums[k]的位置(改变低位的值保证整体值最小)

交换后的[j,end]区间必定是降序的,将[j,end]翻转(k位置的值变大了,为了保证值尽可能小,后面必须是升序)

class Solution {
    public void nextPermutation(int[] nums) {
    int n=nums.length;
    int k=-1;
        
    //step1:先从后往前找第一个升序对(i,j),记录i的坐标为k    
    for(int i=n-2;i>=0;i--)
    {
        int j=i+1;
        if(nums[i]k;i--)
    {
        if(nums[i]>nums[k])
        {
            int t=nums[i];
            nums[i]=nums[k];
            nums[k]=t;
            break;
        }
    }
    
    for(int i=0;i

5、

你可能感兴趣的:(Leetcode热题100,java,算法,leetcode,学习方法,面试,c++)