【问题标题】:Find permutation of one string into other string program查找一个字符串到另一个字符串程序的排列
【发布时间】:2021-09-26 09:54:09
【问题描述】:

尝试编写一个程序来检查string s1 的排列是否存在于string s2 中。

在下面创建的程序,它适用于下面的测试用例。

输入:

s1 = "ab"
s2 = "eidballl"

输出:

True

解释:s2 包含s1 的一个排列(即ba)。

但是当输入 s2="sdfdadddbd" , s1="ab", expected as, false, but got true.

我正试图弄清楚这里缺少什么。使用滑动窗口方法。在c#中我的代码下方:

   public bool CheckInclusion(string s1, string s2) {

        var intCharArray = new int[256];

        foreach(char c in s1)
        {
            intCharArray[c]++;
        }

        int start=0,end=0;
        int count=s1.Length;
        bool found=false;
        while(end<s2.Length)
        {
            if (intCharArray[s2[end]]>0) { count--;}
            intCharArray[s2[end]]--;


                Console.WriteLine("end:" + end + " start:"+ start);
                if(end-start==s1.Length) {

                    if (count==0) {return true;}
                    if (intCharArray[s2[start]]>=0)
                    {
                        count++;
                    }
                    intCharArray[s2[start]]++;
                    start++;
                }
                    end++;
            }
        return false;
        }

【问题讨论】:

  • 代码除了true之外没有其他地方返回任何东西,所以无论算法如何,它都不能说false
  • 编辑为假。
  • 重新思考萨米的话,好吗?将其更改为 false 并不能解决只有一个 return 带有硬编码返回值的事实。当它总是返回 YES 或总是返回 NO 时,你希望它如何决定答案是 YES/NO?
  • 编辑的部分是这样的,if(end-start==s1.Length) {return true;}return false 如果它从未被发现是真的。发布了一个问题以找出我做错的问题。

标签: c# algorithm anagram sliding-window


【解决方案1】:

你需要检查所有排列的字符是否存在于字符串的 [i, i + p.Length) 的任意范围内

static class StringExtensions
{
    public static bool ContainsAnyPermutationOf(this string str, string p)
    {
        Dictionary<char, int> chars_count = p.CreateChar_CountDictionary();

        for (int i = 0; i <= str.Length - p.Length; i++)
        {
            string subString = str.Substring(i, p.Length);
            if (DictionaryMatch(chars_count, subString.CreateChar_CountDictionary()))
            {
                return true;
            }
        }
        return false;
    }

    private static bool DictionaryMatch(Dictionary<char, int> dictionary1, Dictionary<char, int> dictionary2)
    {
        if (dictionary1.Count != dictionary2.Count)
        {
            return false;
        }
        foreach (var kvp in dictionary1)
        {
            if (!dictionary2.ContainsKey(kvp.Key))
            {
                return false;
            }
            dictionary2[kvp.Key] = dictionary2[kvp.Key] - 1;
            if (dictionary2[kvp.Key] == 0)
            {
                dictionary2.Remove(kvp.Key);
            }
        }
        return true;
    }

    private static Dictionary<char, int> CreateChar_CountDictionary(this string str)
    {
        Dictionary<char, int> dic = new Dictionary<char, int>();
        for (int i = 0; i < str.Length; i++)
        {
            if (!dic.ContainsKey(str[i]))
            {
                dic.Add(str[i], default);
            }
            dic[str[i]] = dic[str[i]] + 1;
        }
        return dic;
    }
}

用法:

static void Main(string[] args)
    {
        Console.WriteLine("sdfdadddbd".ContainsAnyPermutationOf("ab"));
    }

【讨论】:

    【解决方案2】:

    我猜这个问题类似于LeetCode 567。这些是简单、高效、低复杂度的公认解决方案:

    C#

    class Solution {
        public bool CheckInclusion(string s1, string s2) {
            int lengthS1 = s1.Length;
            int lengthS2 = s2.Length;
    
            if (lengthS1 > lengthS2)
                return false;
    
            int[] countmap = new int[26];
    
            for (int i = 0; i < lengthS1; i++)
                countmap[s1[i] - 97]++;
    
    
            int[] bCount = new int[26];
    
            for (int i = 0; i < lengthS2; i++) {
                bCount[s2[i] - 97]++;
    
                if (i >= (lengthS1 - 1)) {
                    if (allZero(countmap, bCount))
                        return true;
    
                    bCount[s2[i - (lengthS1 - 1)] - 97]--;
                }
            }
    
            return false;
        }
    
        private bool allZero(int[] s1, int[] s2) {
            for (int i = 0; i < 26; i++) {
                if (s1[i] != s2[i])
                    return false;
            }
    
            return true;
        }
    }
    

    Java

    class Solution {
        public boolean checkInclusion(String s1, String s2) {
            int lengthS1 = s1.length();
            int lengthS2 = s2.length();
    
            if (lengthS1 > lengthS2)
                return false;
    
            int[] countmap = new int[26];
    
            for (int i = 0; i < lengthS1; i++) {
                countmap[s1.charAt(i) - 97]++;
                countmap[s2.charAt(i) - 97]--;
            }
    
            if (allZero(countmap))
                return true;
    
            for (int i = lengthS1; i < lengthS2; i++) {
                countmap[s2.charAt(i) - 97]--;
                countmap[s2.charAt(i - lengthS1) - 97]++;
    
                if (allZero(countmap))
                    return true;
            }
    
            return false;
        }
    
        private boolean allZero(int[] count) {
            for (int i = 0; i < 26; i++)
                if (count[i] != 0)
                    return false;
    
            return true;
        }
    }
    

    Python

    class Solution:
        def checkInclusion(self, s1, s2):
            count_map_s1 = collections.Counter(s1)
            count_map_s2 = collections.Counter(s2[:len(s1)])
    
            for i in range(len(s1), len(s2)):
                if count_map_s1 == count_map_s2:
                    return True
    
                count_map_s2[s2[i]] += 1
                count_map_s2[s2[i - len(s1)]] -= 1
                if count_map_s2[s2[i - len(s1)]] == 0:
                    del(count_map_s2[s2[i - len(s1)]])
    
            return count_map_s2 == count_map_a
    

    参考

    代码在以下链接中解释:


    这两个答案也很有用:

    【讨论】:

    • 感谢您的信息。这样它就起作用了。我在描述中编辑了代码块。我在想,当到达window lengthcount==0 时,它可以通过这块块工作,所以找到匹配但它不起作用。完整代码块已根据上述描述更新,if(end-start==s1.Length) { if (count==0) {return true;} if (intCharArray[s2[start]]&gt;=0) { count++; } intCharArray[s2[start]]++; start++; }
    【解决方案3】:
    private static bool CheckPermutationInclusion(string s1, string s2)
    {
        return Enumerable.Range(0, s2.Length - s1.Length)
                         .Select(i => s2.Substring(i, s1.Length))
                         .Any(x => x.All(y => s1.Contains(y)));
    }
    

    说明:

    别忘了using System.Linq;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-21
      • 1970-01-01
      • 2019-04-17
      • 2021-01-22
      • 1970-01-01
      • 1970-01-01
      • 2022-07-01
      相关资源
      最近更新 更多