Leetcode题解(七)

本文介绍了多种字符串操作和搜索算法的实现,包括所有单词连接后的子串查找、字典序排列、二分查找等,提供了详细的Java代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.substring-with-concatenation-of-all-words

        这道题可以利用hashmap存储L数组里的字符串,并且需要注意的是有几种情况需要重新初始化hashmap,一种就是完成匹配,另一种就是匹配突然中间断开了。用一个k值来记录是否匹配完成,一旦中间断开k置0;用一个e值来记录一次匹配的初始位置,并且用一个布尔值判断是否更新初始位置,用i记录遍历的下标,如果断开了或结束匹配则从当前记录位置的下一个位置开始,如果在匹配过程中则每次坐标增量为字符串数组的元素长度。具体代码如下:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
public class Solution {
    public ArrayList<Integer> findSubstring(String S, String[] L) {
		ArrayList<Integer>  list=new ArrayList<>();
		//HashMap<String, Integer> hMap=new HashMap<>();
		HashMap<String, Integer> hm=new HashMap<>();
		
		int n=L.length;
		int t=L[0].length();
		for(int i=0;i<n;i++)
		{
			if(hm.containsKey(L[i]))
				hm.put(L[i], hm.get(L[i])+1);
			else
				hm.put(L[i], 1);
		}
		int ls=S.length();
		int k=0;
		int i=0;
		boolean flag=true;
		int e=-1;
		while(i<ls-t+1)
		{
			String s=S.substring(i, i+t);
			if(flag)
			{
				e=i;//记录一次匹配的初始位置
				flag=false;
			}
			if(hm.containsKey(s))
			{
				if(hm.get(s)>=1)
				{
					k+=1;
					hm.put(s, hm.get(s)-1);
					if(k==n)
					{
						list.add(e);
						flag=true;
						hm=initMap(hm,L);
						k=0;
						i=e+1;
	
					}
					else
					{
						i=i+t;
					}
				}
				else
				{
					k=0;
					i=e+1;
					flag=true;
					hm=initMap(hm,L);
				}
				
			}
			else
			{
				k=0;
				i=e+1;
				flag=true;
				hm=initMap(hm,L);
			}
		}
		return list;
		
		
        
    }
	public static HashMap<String, Integer> initMap(HashMap<String, Integer> hm,String[] L)//初始化hashmap
	{
		int n=L.length;
		for(int j=0;j<n;j++)
		{
			
			hm.put(L[j], 0);
		}
		for(int j=0;j<n;j++)
		{
			
			hm.put(L[j], hm.get(L[j])+1);
			
		}
		return hm;
	}
}
2.next-permutation

        这是字典序排列的一种情况,只需要求下一个字典序排列即可,相当于递归求全排列的递归只有一层。本题的思路:为了保证是字典序的,需要一个外循环i从右往左遍历,一个内循环j从i+1开始从左往右遍历,i表示当前需要更换的元素,j则需要遍历出i右边比num[i]大且是最小的元素,找到相应的元素之后需要将i与index交换位置,同时为了保证字典序,则使i+1及以后的元素字典序最小,这样保证了要求的排列是下一个字典序排列。同时这种思路也可以求全排列,只需要加个递归即可。

1.下一个字典序排列:

import java.util.*;
public class Solution {
    public void nextPermutation(int[] num) {
		if(num==null||num.length==0)
			return;
		int n=num.length;
		
		for(int i=n-1;i>=0;i--)//为保证按照字典序,需要从后面逐个倒序
		{
			boolean flag=false;//num[i]之后是否存在比num[i]大的元素
			int index=-1;//记录num[i]之后大于num[i]的元素的最小值的下标
			for(int j=i+1;j<n;j++)
			{
				if(num[j]>num[i])//前提是要比num[i]大
				{
					if(index==-1)//index=-1说明这是第一个比num[i]大的元素。
						index=j;
					else {
						if(num[j]<num[index])
							index=j;
					}
					flag=true;//说明存在比num[i]大的元素
				}
			}
			if(flag)//找到了合适的j,需要对i以后的数进行顺序重整
			{
				swap(num,i,index);//首先将i和i后大于i位置的最小元素调换位置,
				Arrays.sort(num,i+1,n);//调换位置之后,需要对i+1及以后的元素排序,这样才满足符合字典序。因为i位置比原来大了一点,只有后面是有序的,才能保证当前顺序是仅大于之前顺序的。
				return ;
				
			}
			
		}
		Arrays.sort(num);//当前面都找不到合适的index时,说明当前是逆序,所以下一个排列就是顺序。
		
    }
	public static void swap(int[] num,int i,int j)
	{
		int temp=num[i];
		num[i]=num[j];
		num[j]=temp;
	}
}
2.字典序全排列
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;


public class Permutation {

	public static void permutation(int[] num)
	{
		if(num==null||num.length==0)
			return;
		int n=num.length;
		System.out.println(Arrays.toString(num));//输出一种排列。
		for(int i=n-1;i>=0;i--)//为保证按照字典序,需要从后面逐个倒序
		{
			boolean flag=false;//num[i]之后是否存在比num[i]大的元素
			int index=-1;//记录num[i]之后大于num[i]的元素的最小值的下标
			for(int j=i+1;j<n;j++)
			{
				if(num[j]>num[i])//前提是要比num[i]大
				{
					if(index==-1)//index=-1说明这是第一个比num[i]大的元素。
						index=j;
					else {
						if(num[j]<num[index])
							index=j;
					}
					flag=true;//说明存在比num[i]大的元素
				}
			}
			if(flag)//找到了合适的j,需要对i以后的数进行顺序重整
			{
				swap(num,i,index);//首先将i和i后大于i位置的最小元素调换位置,
				Arrays.sort(num,i+1,n);//调换位置之后,需要对i+1及以后的元素排序,这样才满足符合字典序。因为i位置比原来大了一点,只有后面是有序的,才能保证当前顺序是仅大于之前顺序的。
				
				permutation(num);
			}
			
		}
		return;
		
		
	}
	public static void swap(int[] arr,int i,int j)
	{
		int temp=arr[i];
		arr[i]=arr[j];
		arr[j]=temp;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr= {1,2,2,4};
		
		permutation(arr);
		

	}

}
3.search-insert-position

        本题可以用二分查找的思路:

import java.util.*;
public class Solution {
    public int searchInsert(int[] A, int target) {
		int index=Arrays.binarySearch(A, target);
		if(index<0)
			index=Math.abs(index)-1;
		return index;
        
    }
}


4.search-in-rotated-sorted-array

        本题只需要遍历一遍即可:
public class Solution {
    public int search(int[] A, int target) {
		int index=-1;
		int n=A.length;
		for(int i=0;i<n;i++)
		{
			if(A[i]==target)
			{
				index=i;
				break;
			}
		}
		return index;
        
    }
}

还可以使用二分思想:

public class Solution {
    public int search(int[] A,int target)
    {
        int n=A.length;
        int left=0;
        int right=n-1;
        int key=A[0];
        int index=-1;
        out:
        while(left<=right)
        {
            int mid=left+(right-left)/2;
            if(A[mid]==target)
            {
                index=mid;
                break out;
            }
            if(A[left]<=A[mid])//left-mid是顺序
            {
            	if(A[left]<=target&&A[mid]>=target)//target在左边
            		right=mid-1;
            	else
            		left=mid+1;
            }
            else//mid-right是有序的
            {
                if(A[right]>=target&&A[mid]<target)//在右边
                    left=mid+1;
                else
                    right=mid-1;//在左边
            }
        }
        return index;
    }
	
}

5.search-for-a-range

        采用二分的思想,首先通过二分查找判断大致区间,如果A[mid]==target,则从mid开始分别往两边扩,从而确定区间。
public class Solution {
    public int[] searchRange(int[] A, int target) {
		int n=A.length;
		int left=0;
		int right=n-1;
		int[] ans= {-1,-1};
		out:
		while(left<=right)
		{
			int mid=left+(right-left)/2;
			if(A[mid]>target)
				right=mid-1;
			else if(A[mid]<target)
				left=mid+1;
			else {
				ans[0]=mid;
				ans[1]=mid;
				while(ans[0]>=0&&A[ans[0]]==target)
					ans[0]--;
				while(ans[1]<n&&A[ans[1]]==target)
					ans[1]++;
				ans[0]++;
				ans[1]--;
				break out;
				
			}
		}
		return ans;
        
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值