1.reverse-nodes-in-k-group
![](https://i-blog.csdnimg.cn/blog_migrate/d7f0e8ccad1f13ec2ee28d94317fb840.png)
这题跟reverse-in-pair的思路有些相同,只不过它是k个一组进行翻转,而rerverse-in-pair是k=2的情况。首先也是建立伪头指针,便于翻转后的链表的连接,另外就是链表的断开与连接,断开比较容易,就是用一个循环控制一组链表的个数即可。另外,链表的连接需要用三个临时变量,一个表示该k个结点链表的原来的头,以及原来的尾,同时需要保存原来的尾的下一个结点,即下k个结点的头。而连接时只需要将结果链表的尾连上当前k个结点的原来的尾即翻转后的头即可。代码如下:
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//先计算长度
int len=0;
ListNode pre=head;
while(pre!=null)
{
pre=pre.next;
len++;
}
if(len<k||head==null||head.next==null||k==1)
return head;
ListNode node=new ListNode(-1);//伪头指针
ListNode res=node;
ListNode temp1=null;
boolean flag=true;
while(len>=k)
{
ListNode temp2=null;
ListNode t=null;//存储原来的头指针,为了与下一个断开的指针连接
for(int i=0;i<k;i++)
{
temp1=head.next;
if(t==null)
t=head;
head.next=temp2;
temp2=head;
head=temp1;
}
res.next=temp2;
flag=false;
res=t;
len-=k;
}
if(temp1!=null)
res.next=head;
return node.next;
}
}
2.count-and-say
![](https://i-blog.csdnimg.cn/blog_migrate/3245e1ff444715f0967002f62eb3b6c1.png)
这道题只需要遍历依次遍历即可,即有统计连续相同数字个数并将其读出来,比如11122结果就是3122表示3个1,2个2.具体实现代码如下:
public class Solution {
public String countAndSay(int n) {
String s="1";
if(n==1)
return s;
for(int i=1;i<n;i++)
{
String temp=solve(s);
s=temp;
}
return s;
}
public String solve(String s) {
int len=s.length();
char c=s.charAt(0);
int k=1;
StringBuilder sb=new StringBuilder();
for(int i=1;i<len;i++)
{
if(s.charAt(i)==c)
{
k+=1;
}
else
{
sb.append(""+k+c);
k=1;
c=s.charAt(i);
}
}
sb.append(""+k+c);
return sb.toString();
}
}
3.combination-sum
![](https://i-blog.csdnimg.cn/blog_migrate/ba342eecee51bf30fa1dd760090d2a9a.png)
这是一个搜索树的问题,采用深度优先搜索算法,并且数组中每个数字可以用多次,其中用一个循环遍历来保证递归次数,并且适当剪枝以及扩展和撤销扩展。
import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
public ArrayList<ArrayList<Integer>> combinationSum(int[] candidates, int target) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> list = new ArrayList<Integer>();
if(candidates == null || candidates.length <= 0) return null;
Arrays.sort(candidates);
dfs(candidates,target,0,list,result);
return result;
}
public static void dfs(int[] candidates, int diff, int start, ArrayList<Integer> list, ArrayList<ArrayList<Integer>> result){
if(diff<0) return;
if(diff == 0){
result.add(new ArrayList<>(list));
return;
}
for (int i = start; i < candidates.length; i++) {
if(diff < candidates[i]) return ;
list.add(candidates[i]);
dfs(candidates,diff-candidates[i],i,list,result);
list.remove(list.size()-1);
}
}
}
看上面代码,可以看出,该搜索树的剪枝条件,即当diff小于0时,说明该搜索路径没有合适的需要return进行返回剪枝,当diff等于0,说明该搜索路径满足条件,则需要将该路径存储,并且返回继续搜索。该算法核心部分就是该for循环,首先for循环控制了递归的深度,说明该递归是有穷尽的,循环遍历数组时,如果当前值比目标值大需要剪枝,否则添加到路径中,然后递归遍历从当前及往后的元素的情况,并且需要更新目标值,注意递归之后有一个remove的操作,即撤销扩展,即搜索当前情况后,需要将路径中的元素逐个踢出并尝试是否有其他合适的值。
4.combination-sum-ii
![](https://i-blog.csdnimg.cn/blog_migrate/ce7aa21df4f5da2d2a077f61b4134209.png)
其实该题与上述第三题思路大致相同,只不过添加了两个约束条件,一个是不可重复,即每次添加一个符合的路径时,需要判断是否存在该路径了,二是每个元素不可重复用,即递归的时候控制递归起始点为当前值的后一个值开始,而非当前值开始。
import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
public ArrayList<ArrayList<Integer>> combinationSum2(int[] candidates, int target) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> list = new ArrayList<Integer>();
if(candidates == null || candidates.length <= 0) return null;
Arrays.sort(candidates);
dfs(candidates,target,0,list,result);
return result;
}
public static void dfs(int[] candidates, int diff, int start, ArrayList<Integer> list, ArrayList<ArrayList<Integer>> result){
if(diff<0) return;
if(diff == 0){
if(!result.contains(list))
result.add(new ArrayList<>(list));
return;
}
for (int i = start; i < candidates.length; i++) {
if(diff<candidates[i]) return;
list.add(candidates[i]);
dfs(candidates,diff-candidates[i],i+1,list,result);
list.remove(list.size()-1);
}
}
}
5.first-missing-positive
![](https://i-blog.csdnimg.cn/blog_migrate/fb77f26ef84a83b04c2440686dab4a76.png)
第一遍遍历将每个数存储在值所对应的下标即可,第二遍遍历可以保证搜索一遍就可以找出目标值。
public class Solution {
public int firstMissingPositive(int[] A) {
int n=A.length;
int res[]=new int[n+1];
int ans=-1;
for(int i=0;i<n;i++)
{
if(A[i]>=0&&A[i]<=n)
res[A[i]]=1;
}
for(int i=1;i<=n;i++)
{
if(res[i]==0)
{
ans=i;
break;
}
}
if(ans==-1)
ans=n+1;
return ans;
}
}