LeetCode 30은 단어의 모든 하위 문자열과 31 개의 다음 순열을 연결합니다.

유지 관리는 정말 쉽지 않습니다. 도움이 필요하면 좋아요를 누르고 팔로우하세요. 공개 계정 bigsai답장 进群을 따라 체크인에 참여하세요.

모든 단어 연결

제목 설명:

문자열 s와 같은 길이의 단어가 주어집니다. 단어의 모든 단어를 연결하여 형성 할 수있는 s에서 하위 문자열의 시작 위치를 찾습니다.
하위 문자열은 단어의 단어와 정확히 일치해야하며 중간에 다른 문자가있을 수 없지만 단어의 순서를 고려할 필요는 없습니다.

예 1 :

입력 :
s = "barfoothefoobarman",
words = [ "foo", "bar"]
출력 : [0,9]
설명 :
인덱스 0과 9에서 시작 하는 하위 문자열은 각각 "barfoo"및 "foobar"입니다.
출력 순서는 중요하지 않으며 [9,0]도 유효한 답입니다.

예 2 :

입력 :
s = "wordgoodgoodgoodbestword",
words = [ "word", "good", "best", "word"]
출력 : []

분석 :
이 질문의 진실을 밝히기위한 기술과 계획이 꽤 있고,이 질문에 많은 생각을 쏟았으며 고려해야 할 점이 조금 더 있습니다. 아이디어는 문자열 s의 특정 문자열이 단어의 모든 단어로 구성 될 수 있음을 찾는 것입니다. 일치하는 하위 문자열을 충족하는 첫 번째 숫자를 반환합니다.

재귀 방법 :
이론적으로는 처리 방법에서 재귀를 사용할 수 있지만 너무 많은 레이어와 개별적인 상대적으로 특수한 데이터로 인해 스택 TL이 버스트 될 수 있습니다. 여기에 교훈이 있습니다.
여기에 사진 설명 삽입
당시 질문을주의 깊게 읽지 않았고, 각 단어의 길이가 같은지 신경 쓰지 않아서 검색 질문이라고 생각했습니다. 나중에 질문을주의 깊게 읽고 문제를 발견했습니다.

일반 해시 방법 (슬라이딩 창)
은 어떤 사람들이 슬라이딩 창이라고 부르는 아름다운 이름입니다. 여기서 간단히 해시 방법이라고 부를 것입니다. 이 문제를 분석하고 처리하는 방법은 무엇입니까? 몇 가지 중요한 조건을 살펴볼 수 있습니다.

  • 단어의 모든 단어는 길이가 같습니다.
  • 모든 단어를 한 번만 사용해야합니다.

즉, 매칭 할 때 단어별로 매칭 할 수 있습니다.
여기에 사진 설명 삽입

그러나 각 문자열을 판단 할 때 여러 단어로 나누어 판단 할 수 있습니다 .
여기에 사진 설명 삽입
두 개의 HashMap을 사용하여 단어 수를 저장하고 저장 중에 판단을 내리고 불만이 있으면 중지하십시오. 끝까지 달릴 수 있다면이 마크를 추가 할 수 있습니다.

구체적인 구현 코드는 다음과 같습니다.

public List<Integer> findSubstring(String s, String[] words) 
{
    
    
	    List<Integer>value=new ArrayList<Integer>();
		Map<String, Integer>map=new HashMap<String, Integer>();
		for(int i=0;i<words.length;i++)
		{
    
    
			int num=map.getOrDefault(words[i], 0);
			map.put(words[i], num+1);
		}
		int wordlen=words[0].length();
		int len=words[0].length()*words.length;
		StringBuilder sBuilder=new StringBuilder(" ");
		sBuilder.append(s.substring(0, len-1));
		for(int i=0;i<s.length()-len+1;i++)
		{
    
    
			sBuilder.deleteCharAt(0);
			sBuilder.append(s.charAt(i+len-1));
			
			int num=0;//统计总共满足的单词数量
			Map<String, Integer>map2=new HashMap<String, Integer>();
			//map2.putAll(map);
			int index=0;
			while (index<len) {
    
    
				String team=sBuilder.substring(index,index+wordlen);
				int number=map2.getOrDefault(team, 0);//次数
				map2.put(team, number+1);
				if(number+1>map.getOrDefault(team, 0))
					break;
				
				index+=wordlen;
			}
			
			if(index==len)
				value.add(i);
				
		}
		return value;
}

여기에 사진 설명 삽입

해시 슬라이딩 윈도우 최적화
위에서 언급 한 슬라이딩 처리에서는 현재 문자열의 HashMap을 재 계산하고 재 매치해야 함을 알 수 있습니다. 이런 식으로 많은 매칭 상황이 낭비됩니다.
여기에 사진 설명 삽입
따라서 반복되는 계산을 제거하기 위해서는 최적화가 필요하며 , 먼저 문자열을 단어 길이 그룹으로 나누어 별도로 계산해야합니다.
여기에 사진 설명 삽입
그런 다음 각 그룹은 세부 진행 중에 간격 일치를 나타 내기 위해 동적으로 오른쪽으로 이동하는 두 개의 포인터가 필요합니다. 일반적으로 맵은 매번 새로 고칠 필요가 없으며 재사용 할 수 있습니다. 좌표 j는 시작을 나타내고 인덱스는 현재 끝을 나타냅니다 .

다음과 같은 상황이 발생할 수 있습니다.

  • 새 단어가 없으면 j와 index가 해당 단어로 이동하고 다시 시작되며 저장된 동적 맵을 지워야합니다.

여기에 사진 설명 삽입

  • 발견 된 단어가 존재하지만 너무 많습니다. 중복 된 단어가 제거 될 때까지 j를 오른쪽으로 이동하고 동시에 동적 맵을 수정해야합니다.

여기에 사진 설명 삽입

  • 일반적으로 색인과지도는 오버레이 일치를 통해 업데이트됩니다.

여기에 사진 설명 삽입

위의 단계가 완료된 후 j + len == index이면 일치가 완료되면이 숫자를 추가합니다. 그러나 동시에 다음 단어가 현재 첫 번째 단어와 같은지 판단 할 수 있으며, 같으면 해당 j와 인덱스를 직접 업데이트하여 결과 집합에 추가하지만 동적 맵을 업데이트 할 필요는 없습니다.
여기에 사진 설명 삽입

위의 최적화 아이디어를 사용하여 코드를 코딩 할 수 있습니다. 구현의 세부 사항, 닫기 전에 열기 등에주의하십시오. 특정 코드는 다음과 같습니다.

  public List<Integer> findSubstring(String s, String[] words) {
    
    
      List<Integer>value=new ArrayList<Integer>();//返回的结果
	Map<String, Integer>map=new HashMap<String, Integer>();//统计单词个数
	for(String team:words)//进行统计
	{
    
    
		int num=map.getOrDefault(team, 0);
		map.put(team, num+1);
	}
	int wordlen=words[0].length();//单个单词的长度
	int len=words[0].length()*words.length;//总长度
	for(int i=0;i<wordlen;i++)//分组分别进行
	{
    
    
		int j=i,index=j;
	    Map<String, Integer>map2=new HashMap<String, Integer>();
		while (j<=s.length()-len&&index+wordlen<=s.length()) {
    
    
			 String word=s.substring(index,index+wordlen);
			 
			 int num=map2.getOrDefault(word, 0);
			 map2.put(word, num+1);
			 if(!map.containsKey(word))//不包含该元素,直接跳过
			 {
    
    
				 
				 j=index+wordlen;
				 map2.clear(); 
			 }
			 else if(map.get(word)<num+1)//元素存在但次数过多
			 {
    
    
				 String teamstr="";
				 while (!(teamstr=s.substring(j,j+wordlen)).equals(word)) {
    
    //找到第一个不相等得
					 map2.put(teamstr, map2.get(teamstr)-1);
					 j+=wordlen;
				}
				 map2.put(teamstr, map2.get(teamstr)-1);
				 j+=wordlen;
			 }
			 index+=wordlen;
			 if(index==j+len)
			 {
    
    
				 value.add(j);
				 while (index+wordlen<=s.length()&&s.substring(j, j+wordlen).equals(s.substring(index, index+wordlen))) {
    
    
					 value.add(j+wordlen);
					 j+=wordlen;index+=wordlen;
				} 
				 String teamstr=s.substring(j,j+wordlen);
				 map2.put(teamstr, map2.get(teamstr)-1);
				 j+=wordlen;
			 }
			
		}
	}
	return value;
}

여기에 사진 설명 삽입

다음 순열

제목 설명 :
다음 순열을 얻는 기능 달성 하기 위해 알고리즘은 주어진 숫자 시퀀스를 사전 식 순서에서 다음으로 큰 순열로 재 배열해야합니다.

다음으로 큰 배열이 없으면 숫자를 가장 작은 배열 (즉, 오름차순)으로 다시 정렬합니다.

현장에서 수정해야하며 여분의 일정한 공간 만 허용됩니다.

다음은 몇 가지 예입니다. 입력은 왼쪽 열에 있고 해당 출력은 오른쪽 열에 있습니다.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

분석 :
전체 배열과 비슷하지만 전체 배열은 아닙니다. 다음 사전 순서를 찾아야합니다.
시퀀스를 분석하면 다음 두 가지 법칙을 찾을 수 있습니다.

먼저 첫 번째 양의 순서를 오른쪽에서 왼쪽으로 바꿉니다.

  • 예를 들어, 12 34 5 4는 3과 4를 교체하여 12 4 5 3이됩니다.

둘째, 교환 간격 에 따라 오른쪽에서 왼쪽으로 역순으로 쌍을 교환합니다 (이중주기).

  • 예를 들어, 위는 12 4 3 5가됩니다.

이를 구현할 때 위치 번호와 같은 문제에주의하십시오. 구체적인 코드는 다음과 같습니다.

 public void nextPermutation(int[] nums) {
    
    
     boolean jud=false;
	 int i,j=0;
	 for( i=nums.length-2;i>=0;i--)
	 {
    
    
		 for( j=nums.length-1;j>i;j--)
		 {
    
    
			 
			 if(!jud&&nums[i]<nums[j])
			 {
    
    
				 int team=nums[i];
				 nums[i]=nums[j];
				 nums[j]=team;
				 jud=true;
				 break;
			 }
		 }
		 if(jud)break;
	 }
            if(jud)
	 for(int k=nums.length-1;k>i;k--)
	 {
    
    
		 for(int m=k-1;m>i;m--)
		 {
    
    
			 if(nums[k]<nums[m])
			 {
    
    
				 int team=nums[k];
				 nums[k]=nums[m];
				 nums[m]=team;
			 }
		 }
	 }
	 int team;
	 if(!jud)
	 for( i=0;i<nums.length/2;i++)
	 {
    
    
		 team=nums[i];
		 nums[i]=nums[nums.length-1-i];
		 nums[nums.length-1-i]=team;
	 }
  }

여기에 사진 설명 삽입
알겠습니다.이 체크인이 여기에 있습니다. 관심 bigsai을 기울여 주셔서 감사합니다. 그룹에 응답하여 체크인에 참여하고 bigsai에 응답하여 pdf 리소스 모음을 받으십시오.
여기에 사진 설명 삽입

추천

출처blog.csdn.net/qq_40693171/article/details/108712706