[LeetCode] 1433. Check If a String Can Break Another String

Given two strings: s1 and s2 with the same size, check if some permutation of string s1 can break some permutation of string s2 or vice-versa. In other words s2 can break s1 or vice-versa.

A string x can break string y (both of size n) if x[i] >= y[i] (in alphabetical order) for all i between 0 and n-1

Example 1:

Input: s1 = "abc", s2 = "xya"
Output: true
Explanation: "ayx" is a permutation of s2="xya" which can break to string "abc" which is a permutation of s1="abc".

Example 2:

Input: s1 = "abe", s2 = "acd"
Output: false 
Explanation: All permutations for s1="abe" are: "abe", "aeb", "bae", "bea", "eab" and "eba" and all permutation for s2="acd" are: "acd", "adc", "cad", "cda", "dac" and "dca". However, there is not any permutation from s1 which can break some permutation from s2 and vice-versa.

Example 3:

Input: s1 = "leetcodee", s2 = "interview"
Output: true

Constraints:

  • s1.length == n
  • s2.length == n
  • 1 <= n <= 10^5
  • All strings consist of lowercase English letters.

检查一个字符串是否可以打破另一个字符串。

给你两个字符串 s1 和 s2 ,它们长度相等,请你检查是否存在一个 s1  的排列可以打破 s2 的一个排列,或者是否存在一个 s2 的排列可以打破 s1 的一个排列。

字符串 x 可以打破字符串 y (两者长度都为 n )需满足对于所有 i(在 0 到 n - 1 之间)都有 x[i] >= y[i](字典序意义下的顺序)。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/check-if-a-string-can-break-another-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我这里提供两种思路,一种是直接对两个input字符串排序,一种是利用counting sort计数排序。

首先是简单的排序做法。因为题意判断一个字符串的某个排列是否能被另一个字符串的某个排列打破,那么我们的思路是先对两个input字符串都取他们各自字典序最小的排列permutation。拿到这两个排列之后,我们按字母比较,需要判断的是某一个排列的每个字母是不是都严格小于等于 或者 大于等于另一个排列,如果是则返回true。

时间O(nlogn)

空间O(1)

Java实现

 1 class Solution {
 2     public boolean checkIfCanBreak(String s1, String s2) {
 3         // corner case
 4         if (s1.length() == 0 && s2.length() == 0) {
 5             return false;
 6         }
 7 
 8         // normal case
 9         int len = s1.length();
10         char[] word1 = s1.toCharArray();
11         char[] word2 = s2.toCharArray();
12         Arrays.sort(word1);
13         Arrays.sort(word2);
14         return compare(word1, word2, len) || compare(word2, word1, len);
15     }
16 
17     private boolean compare(char[] word1, char[] word2, int len) {
18         int i = 0;
19         while (i < len) {
20             if (word1[i] - word2[i] >= 0) {
21                 i++;
22             } else {
23                 return false;
24             }
25         }
26         return true;
27     }
28 }

再来是计数排序的做法。因为题目说了只有小写字母所以我们用两个长度为26的数组 array1 和 array2 分别统计一下两个input字符串中每个字母的出现次数。统计好之后,再次遍历这两个数组,并用两个flag记录到底谁的字典序更大。开始遍历的时候,我们用两个变量count1 和 count2 分别统计 array1 和 array2中字母出现次数的累加和,如果中间出现反转,则说明是错的;若直到遍历完,累加和一直都是一个单词大于另一个单词,则返回true。

这个思路不是非常直观,我配合例子讲解一下。比如第二个例子,Input: s1 = "abe", s2 = "acd"。首先我们用 array1 和 array2 数组分别统计字母出现次数,然后再遍历两个 count 数组,计算累加和。由于我们是按照字母顺序来遍历count数组的(这里其实是隐式地在判断两个单词各自字典序最大的permutation之间到底谁大谁小),所以在 a 之后,会先对 count1 累加字母 b 的count,这样导致 count1 > count2, 从而flag1 = true,意思是我们如果在此时停下,第一个单词的累加和更大,所以他的字典序是更大的;但是我们接着往后遍历的时候,发觉分别加完e和d之后,累加和不能保持count1 > count2了,说明此时打破了之前发现的字典序的大小关系了,所以return false。

时间O(n)

空间O(n)

Java实现

 1 class Solution {
 2     public boolean checkIfCanBreak(String s1, String s2) {
 3         int len = s1.length();
 4         int[] array1 = new int[26];
 5         int[] array2 = new int[26];
 6         for (int i = 0; i < len; i++) {
 7             array1[s1.charAt(i) - 'a']++;
 8         }
 9         for (int i = 0; i < len; i++) {
10             array2[s2.charAt(i) - 'a']++;
11         }
12         boolean f1 = false;
13         boolean f2 = false;
14         int count1 = 0;
15         int count2 = 0;
16         for (int i = 0; i < 26; i++) {
17             count1 += array1[i];
18             count2 += array2[i];
19             if (count1 > count2) {
20                 if (f2) {
21                     return false;
22                 }
23                 f1 = true;
24             } else if (count2 > count1) {
25                 if (f1) {
26                     return false;
27                 }
28                 f2 = true;
29             }
30         }
31         return true;
32     }
33 }

LeetCode 题目总结

原文地址:https://www.cnblogs.com/cnoodle/p/14014034.html