简体   繁体   English

在C ++中找到左右相等的最长子串

[英]To find the longest substring with equal sum in left and right in C++

I was solving a question, with which I am having some problems: 我正在解决一个问题,我遇到了一些问题:

Complete the function getEqualSumSubstring, which takes a single argument. 完成函数getEqualSumSubstring,它接受一个参数。 The single argument is a string s , which contains only non-zero digits. 单个参数是一个字符串s ,它只包含非零数字。 This function should print the length of longest contiguous substring of s , such that the length of the substring is 2*N digits and the sum of the leftmost N digits is equal to the sum of the rightmost N digits. 此函数应打印s的最长连续子串的长度,使得子串的长度为2 * N位,并且最左边的N位的总和等于最右边的N位的总和。 If there is no such string, your function should print 0. 如果没有这样的字符串,则您的函数应该打印0。

int getEqualSumSubstring(string s) {
int i=0,j=i,foundLength=0;
    for(i=0;i<s.length();i++)
    {
        for(j=i;j<s.length();j++)
        {
            int temp = j-i;
            if(temp%2==0)
            {
                int leftSum=0,rightSum=0;
                string tempString=s.substr(i,temp);
                for(int k=0;k<temp/2;k++)
                {
                    leftSum=leftSum+tempString[k]-'0';
                    rightSum=rightSum+tempString[k+(temp/2)]-'0';
                }
                if((leftSum==rightSum)&&(leftSum!=0))
                    if(s.length()>foundLength)
                    foundLength=s.length(); 
            }
        }
    }
    return(foundLength);

}

The problem is that this code is working for some samples and not for the others. 问题是这个代码适用于某些样本而不适用于其他样本。 Since this is an exam type question I don't have the test cases either. 由于这是一个考试类型的问题,我也没有测试用例。

This code works 这段代码有效

int getEqualSumSubstring(string s) {
    int i=0,j=i,foundLength=0;
    for(i=0;i<s.length();i++)
    {
        for(j=i;j<s.length();j++)
        {
            int temp = j-i+1;

            if(temp%2==0)
            {
                int leftSum=0,rightSum=0;
                string tempString=s.substr(i,temp);
                // printf("%d ",tempString.length());
                for(int k=0;k<temp/2;k++)
                {
                    leftSum=leftSum+tempString[k]-48;
                    rightSum=rightSum+tempString[k+(temp/2)]-48;
                }
                if((leftSum==rightSum)&&(leftSum!=0))
                    if(tempString.length()>foundLength)
                    foundLength=tempString.length(); 
            }
        }
    }
    return(foundLength);
}

The temp variable must be j-i+1. temp变量必须是j-i + 1。 Otherwise the case where the whole string is the answer will not be covered. 否则,将不包括整个字符串作为答案的情况。 Also, we need to make the change suggested by Scott. 此外,我们需要做出Scott建议的更改。

Here's my solution that I can confirm works. 这是我的解决方案,我可以确认工作。 The ones above didn't really work for me - they gave me compile errors somehow. 上面的那些对我来说并没有真正起作用 - 他们以某种方式给了我编译错误。 I got the same question on InterviewStreet, came up with a bad, incomplete solution that worked for 9/15 of the test cases, so I had to spend some more time coding afterwards. 我在InterviewStreet上得到了同样的问题,提出了一个不错的,不完整的解决方案,适用于9/15的测试用例,因此我不得不花费更多时间编写代码。

The idea is that instead of caring about getting the left and right sums (which is what I initially did as well), I will get all the possible substrings out of each half (left and right half) of the given input, sort and append them to two separate lists, and then see if there are any matches. 我的想法是,不是关心获得左右总和(这也是我最初做的),我将从给定输入的每一半(左半部分和右半部分)中获取所有可能的子串,排序和追加他们到两个单独的列表,然后看看是否有任何匹配。

Why? 为什么?

Say the strings "423" and "234" have the same sum; 假设字符串“423”和“234”具有相同的总和; if I sorted them, they would both be "234" and thus match. 如果我对它们进行排序,它们都将是“234”并因此匹配。 Since these numbers have to be consecutive and equal length, I no longer need to worry about having to add them up as numbers and check. 由于这些数字必须是连续且相等的长度,我不再需要担心必须将它们作为数字添加并检查。

So, for example, if I'm given 12345678, then on the left side, the for-loop will give me: 所以,例如,如果我给了12345678,那么在左侧,for循环将给我:

[1,12,123,1234,2,23,234,3,34] [1,12,123,1234,2,23,234,3,34]

And on the right: 在右边:

[5,56,567,5678,...] [5,56,567,5678,...]

And so forth. 等等。

However, I'm only taking substrings of a length of at least 2 into account. 但是,我只考虑了至少为2的长度的子串。

I append each of these substrings, sorted by converting into a character array then converting back into a string, into ArrayLists. 我将每个子字符串附加到ArrayLists中,这些子字符串通过转换为字符数组然后转换回字符串进行排序。

So now that all this is done, the next step is to see if there are identical strings of the same numbers in these two ArrayLists. 现在所有这一切都已完成,下一步是查看这两个ArrayLists中是否存在相同数字的相同字符串。 I simply check each of temp_b's strings against temp_a's first string, then against temp_a's second string, and so forth. 我只是根据temp_a的第一个字符串检查每个temp_b的字符串,然后针对temp_a的第二个字符串检查,依此类推。

If I get a match (say, "234" and "234"), I'll set the length of those matching substrings as my tempCount (tempCount = 3). 如果我得到一个匹配(比如“234”和“234”),我会将那些匹配的子串的长度设置为我的tempCount(tempCount = 3)。 I also have another variable called 'count' to keep track of the greatest length of these matching substrings (if this was the first occurrence of a match, then count = 0 is overwritten by tempCount = 3, so count = 3). 我还有另一个名为'count'的变量来跟踪这些匹配子串的最大长度(如果这是第一次出现匹配,则count = 0被tempCount = 3覆盖,因此count = 3)。

As for the odd/even string length with the variable int end , the reason for this is because in the line of code s.length()/2+j, is the length of the input happened to be 11, then: 至于带有变量int end的奇数/偶数字符串长度,原因是因为在代码行s.length()/ 2 + j中,输入的长度恰好是11,那么:

s.length() = 11 s.length()= 11

s.length()/2 = 11/5 = 5.5 = 5 s.length()/ 2 = 11/5 = 5.5 = 5

So in the for-loop, s.length()/2 + j, where j maxes out at s.length()/2, would become: 所以在for循环中,s.length()/ 2 + j,其中j在s.length()/ 2处最大,将变为:

5 + 5 = 10 5 + 5 = 10

Which falls short of the s.length() that I need to reach for to get the string's last index. 这不足以获得字符串最后一个索引所需的s.length()。

This is because the substring function requires an end index of one greater than what you'd put for something like charAt(i). 这是因为子字符串函数需要的结束索引比您为charAt(i)更大的结束索引。

Just to demonstrate, an input of "47582139875" will generate the following output: [47, 457, 4578, 24578, 57, 578, 2578, 58, 258, 28] <-- substrings from left half [139, 1389, 13789, 135789, 389, 3789, 35789, 789, 5789, 578] <-- substrings from right half 578 <-- the longest one that matched 6 <-- the length of '578' x 2 只是为了演示,输入“47582139875”将产生以下输出:[47,457,4578,24578,57,578,2578,58,258,28] < - 来自左半部分的子串[139,1389,13789 ,135789,389,3789,35789,789,5789,578] < - 来自右半部分的子串578 < - 最长的匹配6 < - 长度'578'x 2

public static int getEqualSumSubtring(String s){

    // run through all possible length combinations of the number string on left and right half
    // append sorted versions of these into new ArrayList

    ArrayList<String> temp_a = new ArrayList<String>();
    ArrayList<String> temp_b = new ArrayList<String>();

    int end; // s.length()/2 is an integer that rounds down if length is odd, account for this later 

    for( int i=0; i<=s.length()/2; i++ ){
        for( int j=i; j<=s.length()/2; j++ ){
            // only account for substrings with a length of 2 or greater
            if( j-i > 1 ){ 
                char[] tempArr1 = s.substring(i,j).toCharArray();
                Arrays.sort(tempArr1);
                String sorted1 = new String(tempArr1);
                temp_a.add(sorted1);
                //System.out.println(sorted1);

                if( s.length() % 2 == 0 )
                    end = s.length()/2+j;
                else // odd length so we need the extra +1 at the end
                    end = s.length()/2+j+1; 
                char[] tempArr2 = s.substring(i+s.length()/2, end).toCharArray();
                Arrays.sort(tempArr2);
                String sorted2 = new String(tempArr2);
                temp_b.add(sorted2);
                //System.out.println(sorted2);
            }

        }

    }

    // For reference
    System.out.println(temp_a);
    System.out.println(temp_b);

    // If the substrings match, it means they have the same sum

    // Keep track of longest substring
    int tempCount = 0 ;
    int count = 0;
    String longestSubstring = "";

    for( int i=0; i<temp_a.size(); i++){
        for( int j=0; j<temp_b.size(); j++ ){
            if( temp_a.get(i).equals(temp_b.get(j)) ){

                tempCount = temp_a.get(i).length();

                if( tempCount > count ){
                    count = tempCount;
                    longestSubstring = temp_a.get(i);

                }
            }

        }
    }

    System.out.println(longestSubstring);
    return count*2;
}

Heres my solution to this question including tests. 继承了我对这个问题的解决方案,包括测试。 I've added an extra function just because I feel it makes the solution way easier to read than the solutions above. 我添加了一个额外的功能只是因为我觉得它使解决方案比上面的解决方案更容易阅读。

#include <string>
#include <iostream>

using namespace std;

int getMaxLenSumSubstring( string s ) 
{
    int N = 0; // The optimal so far...

int leftSum = 0, rightSum=0, strLen=s.size();
int left, right;

for(int i=0;i<strLen/2+1;i++) {
    left=(s[i]-int('0')); right=(s[strLen-i-1]-int('0'));
    leftSum+=left; rightSum+=right;

    if(leftSum==rightSum) N=i+1;
}

return N*2;
}

int getEqualSumSubstring( string s ) {
    int maxLen = 0, substrLen, j=1;

for( int i=0;i<s.length();i++ ) {
    for( int j=1; j<s.length()-i; j++ ) {
        //cout<<"Substring = "<<s.substr(i,j);
        substrLen = getMaxLenSumSubstring(s.substr(i,j));
        //cout<<", Len ="<<substrLen;
        if(substrLen>maxLen) maxLen=substrLen;
    }
}

return maxLen;
}

Here are a few tests I ran. 以下是我运行的一些测试。 Based upon the examples above they seem right. 基于上面的例子,他们似乎是对的。

int main() {
    cout<<endl<<"Test 1 :"<<getEqualSumSubstring(string("123231"))<<endl;

    cout<<endl<<"Test 2 :"<<getEqualSumSubstring(string("986561517416921217551395112859219257312"))<<endl;

    cout<<endl<<"Test 3:"<<getEqualSumSubstring(string("47582139875"))<<endl;

}
 Below is my code for the question... Thanks !!


    public class IntCompl {

        public String getEqualSumSubstring_com(String s)
        {
            int j;
            int num=0;
            int sum = 0;
            int m=s.length();

            //calculate String array Length

            for (int i=m;i>1;i--)
            {
                sum = sum + m;
                m=m-1;
            }
            String [] d = new String[sum];
            int k=0;
            String ans = "NULL";

            //Extract strings

            for (int i=0;i<s.length()-1;i++)
            {
            for (j=s.length();j>=i+1;k++,j--)
            {
                num = k;
                d[k] = s.substring(i,j);
            }
            k=num+1;
            }

            //Sort strings in such a way that the longest strings precede...

            for (int i=0; i<d.length-1; i++)
            {
                for (int h=1;h<d.length;h++)
                {
                if (d[i].length() > d[h].length())
                 {
                    String temp;
                    temp=d[i];
                    d[i]=d[h];          
                    d[h]=temp;
                 }
                }       
            }

            // Look for the Strings with array size 2*N (length in even number) and such that the 
            //the sum of left N numbers is = to the sum of right N numbers.
            //As the strings are already in decending order, longest string is searched first and break the for loop once the string is found.

            for (int x=0;x<d.length;x++)
            {
                int sum1=0,sum2=0;
                if (d[x].length()%2==0 && d[x].length()<49)
                {
                    int n;
                    n = d[x].length()/2;
                    for (int y=0;y<n;y++)
                    {
                        sum1 = sum1 + d[x].charAt(y)-'0';
                    }
                    for (int y=n;y<d[x].length();y++)
                    {
                        sum2 = sum2 + d[x].charAt(y)-'0';
                    }
                    if (sum1==sum2)
                    {
                        ans = d[x];
                        break;
                    }

                }
            }
                return ans;

            }
        }

Here is the complete Java Program for this question. 这是这个问题的完整Java程序。 Complexity is O(n^3) This can however be solved in O(n^2).For O(n^2) complexity solution refer to this link 复杂度为O(n ^ 3)然而,这可以在O(n ^ 2)中求解。对于O(n ^ 2)复杂度解,请参考此链接

import java.util.Scanner;
import static java.lang.System.out;
 public class SubStringProblem{
  public static void main(String args[]){
 Scanner sc = new Scanner(System.in);
 out.println("Enter the Digit String:");
 String s = sc.nextLine();
 int n = (new SubStringProblem()).getEqualSumSubString(s);
 out.println("The longest Sum SubString is "+n);
 }
    public int getEqualSumSubString(String s){
 int N;
 if(s.length()%2==0)
 {
    //String is even
    N = s.length();     
 }
 else{ 
    //String is odd
    N=s.length()-1;
 }
 boolean flag =false;
 int sum1,sum2;
 do{    
    for(int k=0;k<=s.length()-N;k++){   
        sum1=0;
        sum2=0;
        for(int i =k,j=k+N-1;i<j;i++,j--)
        {   
            sum1=sum1 + Integer.parseInt(s.substring(i,i+1));
            sum2+=Integer.parseInt(s.substring(j,j+1));
        }
        if(sum1==sum2){
        return N;
        }
    }   
    N-=2;
 flag =true;
}while(N>1);
return -1;
}
}

Shouldn't the following code use tempString.length() instead of s.length() 以下代码不应该使用tempString.length()而不是s.length()

if((leftSum==rightSum)&&(leftSum!=0))
    if(s.length()>foundLength)
        foundLength=s.length(); 

What is your rationale for the number 48 on these two lines? 你对这两行中48号的理由是什么?

for(int k=0;k<temp/2;k++)
{
    leftSum=leftSum+tempString[k]-48;
    rightSum=rightSum+tempString[k+(temp/2)]-48;
}

I am just overly curious and would like to hear the reasoning behind it, because I have a similar solution, but without the 48 and it still works. 我只是过于好奇并想听听背后的原因,因为我有一个类似的解决方案,但没有48,它仍然有效。 However, I added the 48 an still got the correct answer. 但是,我添加了48仍然得到了正确的答案。

Simple solution. 简单解决方案 O(n*n). O(N * N)。 s - input string. s - 输入字符串。

var longest = 0;
for (var i = 0; i < s.length-1; i++) {
    var leftSum = rightSum = 0;

    for (var j = i, k = i+1, l = 2; j >=0 && k < s.length; j--, k++, l+=2) {
        leftSum += parseInt(s[j]);
        rightSum += parseInt(s[k]);

        if (leftSum == rightSum && l > longest) {
            longest = l;
        }
    }
}

console.log(longest);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM