Leetcode题解(八)

1.reverse-nodes-in-k-group

这题跟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

        这道题只需要遍历依次遍历即可,即有统计连续相同数字个数并将其读出来,比如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

这是一个搜索树的问题,采用深度优先搜索算法,并且数组中每个数字可以用多次,其中用一个循环遍历来保证递归次数,并且适当剪枝以及扩展和撤销扩展。

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

        其实该题与上述第三题思路大致相同,只不过添加了两个约束条件,一个是不可重复,即每次添加一个符合的路径时,需要判断是否存在该路径了,二是每个元素不可重复用,即递归的时候控制递归起始点为当前值的后一个值开始,而非当前值开始。

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

第一遍遍历将每个数存储在值所对应的下标即可,第二遍遍历可以保证搜索一遍就可以找出目标值。

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;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值