目录
LeetCode 第22题: 括号生成
LeetCode 第23题:合并k个升序链表
LeetCode 第24题:两两交换链表中的节点
LeetCode 第22题: 括号生成
题目描述
数字n代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且有效的括号组合。
难度:中等
题目链接:22. 括号生成 - 力扣(LeetCode)
示例1:
输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"]
示例2:
输入:n = 1 输出:["()"]
提示:1<=n<=8
解题思路:
回溯法
- 使用StringBuilder构建当前括号组合
- 记录已使用的左括号和右括号数量
- 递归尝试添加左括号或右括号
- 满足条件时将结果加入列表
public class Solution {public IList<string> GenerateParenthesis(int n){List<string> result = new List<string>();BackTrack(result,new StringBuilder(),0,0,n);return result;}private void BackTrack(List<string> result,StringBuilder current,int leftCount,int rightCount,int n){//如果当前字符串长度等于2n,说明找到了一个有效组合if(current.Length==n*2) result.Add(current.ToString()),return;//如果左括号数量小于n,可以添加左括号if(leftCount<n){current.Append('(');BackTrack(result,current,leftCount+1,rightCount,n);current.Length--;//回溯,删除刚才添加的括号}//如果右括号数量小于左括号数量,可以添加右括号if(rightCount<leftCount){current.Append(')');BackTrack(result,current,leftCount,rightCount+1,n);current.Length--;}}}
LeetCode 第23题:合并k个升序链表
题目描述
给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。
难度:困难
题目链接:23. 合并 K 个升序链表 - 力扣(LeetCode)
示例1:
输入:lists = [[1,4,5],[1,3,4],[2,6]] 输出:[1,1,2,3,4,4,5,6] 解释:链表数组如下: [1->4->5,1->3->4,2->6 ] 合并后: 1->1->2->3->4->4->5->6
示例2:
输入:lists = [] 输出:[]
示例3:
输入:lists = [[]] 输出:[]
提示:
- k==lists.length
- 0<=k<=10^4
- 0<=lists[i].length<=500
- -10^4<=lists[i][j]<=10^4
- lists[i]按升序排列
- lists[i].length的总和不超过10^4
解题思路:
方法一:分治合并
将k个链表的合并问题分解为两两合并的子问题
- 如果链表数组为空,返回null
- 如果只有一个链表,直接返回
- 将链表数组分为两半
- 递归合并左半部分和右半部分
- 合并得到的两个链表
public class Solution {public ListNode MergeKLists(ListNode[] lists){if(lists==null || lists.length==0) return null;return MergeSort(lists,0,lists.length-1);}private ListNode MergeSort(ListNode[] lists,int left,int right){if(left==right) return lists[left];if(left>right) return null;int mid = left+(right-left)/2;ListNode leftList = MergeSort(lists,left,mid);ListNode rightList = MergeSort(lists,mid+1,right);return MergeTwoLists(leftList,rightList);}private ListNode MergeTwoLists(ListNode l1,ListNode l2){ListNode dummy = new ListNode(0);ListNode current = dummy;while(l1!=null && l2!=null){if(l1.val<=l2.val) current.next = l1,l1=l1.next;else current.next = l2,l2=l2.next;current = current.next;}current.next = l1 ?? l2;return dummy.next;}}
方法二:优先队列
使用优先队列(最小堆)来维护k个链表的当前最小节点。
- 创建最小堆,将k个链表的头节点加入堆中
- 每次从堆中取出最小节点,加入结果链表
- 如果被取出的节点有后继节点,将后继节点加入堆中
- 重复2~3步骤直到堆为空。
public class Solution {public ListNode MergeKLists(ListNode[] lists){if(lists==null lists.length==0) return null;//创建优先队列,按节点值升序排序var pq = new PriorityQueue<ListNode,int>();//将所有链表的头节点加入队列foreach(var list in lists){if(list!=null) pq.Enqueue(list,list.val);}ListNode dummy = new ListNode(0);ListNode current = dummy;//不断从队列中取出最小节点while(pq.Count>0){ListNode node = pq.Dequeue();current.next = node;current = current.next;//如果取出的节点还有后继节点,将后继节点加入队列if(node.next!=null) pq.Enqueue(node.next,node.next.val);}return dummy.next;}}
LeetCode 第24题:两两交换链表中的节点
题目描述
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即只能进行节点交换) 。
难度:中等
题目链接:24. 两两交换链表中的节点 - 力扣(LeetCode)
示例1:
输入:head = [1,2,3,4] 输出:[2,1,4,3]
示例2:
输入:head = [] 输出:[]
示例3:
输入:head = [1] 输出:[1]
提示:
- 链表中节点的数目在范围[0,100]内
- 0<=Node.val<=100
解题思路:递归法
- 基线条件:空链表或只有一个节点
- 对于每两个节点:
- 交换这两个节点
- 递归处理后续节点
- 返回新的头节点
public class Solution {public ListNode SwapPairs(ListNode head){//基线条件:空链表或只有一个节点if(head==null || head.next==null) return head;//获取要交换的两个节点ListNode first = head;ListNode second = head.next;//保存后续节点并递归处理ListNode next = second.next;second.next = first;first.next = SwapPairs(next);return second;}}