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