40.组合求和II
1.题目描述
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
①所有数字(包括目标数)都是正整数
②解集不能包含重复的组合。
1.1示例
2.代码
分析:首先,想到的就是回溯方法。因为考虑到重复的问题,我是使用了set集合来进行去重。接下来就是撸代码了,整体思路还是比较清晰的。实际上代码还需改进。
class Solution {
//先定义一个结果集
List<List<Integer>> res;
//生成一个set进行去重
Set<List<Integer>> set;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
res=new ArrayList<>();
set=new HashSet<>();
//判断candidates非空
if(candidates==null || candidates.length==0){
return res;
}
int len=candidates.length;
//排序一下数组
Arrays.sort(candidates);
//进行回溯
traceback(candidates,0,new Stack<Integer>(),target,0);
//返回结果集
return res;
}
private void traceback(int[] candidates,int start,Stack<Integer> st,int target,int sum){
//如果sum==target,说明已经找到了一组数
if(sum==target){
//判断该一组数是否已经存在于res中
if(!set.contains(new ArrayList(st))){
set.add(new ArrayList(st));
res.add(new ArrayList(st));
}
return;
}
//如果回溯到末尾,或者sum已经大于targe值,可以返回
if(start==candidates.length || sum>target){
return;
}
//进行遍历
for(int i=start;i<candidates.length;i++){
//使用stack结果的st来保存数据
st.push(candidates[i]);
sum +=candidates[i];
//继续回溯
traceback(candidates,i+1,st,target,sum);
sum -=candidates[i];
//pop出顶层元素
st.pop();
}
}
}
25.K个一组翻转链表
1.题目描述
给定一个链表,每k个节点一组进行翻转,请你返回翻转后的链表。
k是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是k的整数倍,那么请将最后剩余的节点保持原有顺序。
1.1 示例
说明:
①你的算法只能使用常数的额外空间。
②你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
2.代码
分析:首先,我们知道需要一个翻转链表的方法。但是这一个链表是有长度要求的,且还需要记录它的首节点和尾结点,所以我们返回一个listNode数组,来记录它的首节点和尾结点。最后,在主代码中分贝指向listNode[0]和listNode[1]即可。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//判断非空性
if(head==null || head.next==null){
return head;
}
//如果k=1,可以直接返回head
if(k==1){
return head;
}
//设置一个辅助首节点dummy
ListNode dummy=new ListNode(0);
//cur节点表示当前节点
ListNode cur=head;
//pre节点表示前一部分链表的尾结点
ListNode pre=dummy;
//用来记录当前节点数
int count=0;
//first表示需要翻转链表的首节点
ListNode first=head;
//tmp节点用来存储后一部分链表的首节点
ListNode tmp=null;
while(cur!=null){
count++;
//表示已有k个节点,可以进行翻转了
if(count==k){
//存储后一节点
tmp=cur.next;
//取出需要当前翻转链表
cur.next=null;
//进行翻转
ListNode[] node=reverse(first);
//连接前一部分链表
pre.next=node[0];
//pre为当前已翻转完成的链表的尾结点
pre=node[1];
//重新计数
count=0;
//cur为下一部分链表的开始位置
cur=tmp;
//存储之后需要翻转的链表的首节点
first=tmp;
}else{
cur=cur.next;
}
}
//连接前后两部分链表
pre.next=first;
//返回辅助节点的next节点,就是翻转后链表的首节点
return dummy.next;
}
//返回一个listNode数组,记录翻转后链表的首节点和尾结点。
private ListNode[] reverse(ListNode head){
//判断非空性
if(head==null || head.next==null){
return new ListNode[]{null,null};
}
ListNode dummy=head;
ListNode pre=null;
ListNode cur=head;
//翻转链表
while(cur!=null){
ListNode tmp=cur.next;
cur.next=pre;
pre=cur;
cur=tmp;
}
return new ListNode[]{pre,dummy};
}
}
第一题链接: https://leetcode-cn.com/problems/combination-sum-ii/.
第二题链接: https://leetcode-cn.com/problems/reverse-nodes-in-k-group/.