【问题标题】:Extracting the Most Phrases up to X number of Words提取最多 X 个单词的短语
【发布时间】:2017-11-28 18:47:10
【问题描述】:

我有一个有趣的算法/java 问题,我认为我“击败”并且超级简单,但结果我没有得到想要的输出:

您有一串短语。为简单起见,将它们视为整数长度。

String s= "我是汤姆" 将作为 [1,2,3] 存储在整数数组中,其中每个表示字符串中每个单词的长度。

编写一个方法来计算最长的子序列,使其小于或等于给定的 k 值。

Input: 
3 //length of array 
1 //a[0] 
2 //a[1] 
3 //a[2] 
4 // value of k 

Output: 
2 

Input: 
4 //length of array 
3 
1 
2 
1 
4 //value of k 

Output: 
3 

我最初的想法是好的,这非常容易,我要对这个数组进行排序(没有说你不能),理论上所有最小的数字都应该排在第一位。逐个索引遍历数组索引,直到<= k 不再为真。然后我针对给定的测试运行它,它通过了前 2 个并在第 3 个失败。这是我的排序和添加代码:

// k is the number we want to sum the phrases up to
// a is the length of a phrase
// Need to add phrases together to get the most phrases less than or equal to k
// Algorithm: Probably want to sort the list then add from the front until > k
static int maxLength(int[] a, int k) {
    int sum = 0;
    int numPhrases = 0;

    Arrays.sort(a);

    for(int i = 0; i < a.length; i++) {

        if((sum + a[i]) <= k) {
            sum += a[i];
            numPhrases++;
        }

    }

    return numPhrases;
}

我们得到了以下不可编辑的代码(连同导入):

public static void main(String[] args) throws IOException{
        Scanner in = new Scanner(System.in);
        final String fileName = System.getenv("OUTPUT_PATH");
        BufferedWriter bw = new BufferedWriter(new FileWriter(fileName));
        int res;

        int _a_size = 0;
        _a_size = Integer.parseInt(in.nextLine().trim());
        int[] _a = new int[_a_size];
        int _a_item;
        for(int _a_i = 0; _a_i < _a_size; _a_i++) {
            _a_item = Integer.parseInt(in.nextLine().trim());
            _a[_a_i] = _a_item;
        }

        int _k;
        _k = Integer.parseInt(in.nextLine().trim());

        res = maxLength(_a, _k);
        bw.write(String.valueOf(res));
        bw.newLine();

        bw.close();
}

这基本上完成了所有工作,只为您提供了数字 k(您可以添加的单词)和您要添加的数字数组。

它在以下测试中坏了:

Input:
61
74    
659    
931    
273
545
879
924
710   
441   
166   
493  
43   
988   
504   
328  
730   
841  
613   
304  
170 
710  
158 
561  
934  
100 
279  
817 
336
98 
827 
513
268
811
634
980
150
580
822
968
673
394
337
486
746
229
92
195
358
2
154
709
945
669
491
125
197
531
904
723
667
550
22337

预期输出为46

我的程序在这里输出51

感谢您的帮助,我很困惑为什么这是不正确的。

【问题讨论】:

  • 这听起来像是背包问题。对于您显示的少量输入,有一个绝对解决方案。通常,您将不得不使用启发式算法,而贪心算法无论如何都不是最优的。
  • 鉴于您正在处理数字,“我是汤姆”与问题有什么关系?
  • (sum + a[i]) &lt;= k这个条件为假时,我认为你需要打破循环。
  • @EleazarEnrique 为假时不加数字,因此不增加 numPhrases+=
  • 你能粘贴确切的问题陈述吗?没有办法返回 46 和 sum > k

标签: java arrays algorithm


【解决方案1】:

阅读声明后,

解决方案位于: http://www.geeksforgeeks.org/longest-subarray-sum-elements-atmost-k/

static int maxLength(int[] arr, int k) {
    int sum = 0;
    int cnt = 0, maxcnt = 0;

    for (int i = 0; i < arr.length; i++) {

        // If adding current element doesn't
        // cross limit add it to current window
        if ((sum + arr[i]) <= k) {
            sum += arr[i];
            cnt++;
        }

        // Else, remove first element of current
        // window.
        else if (sum != 0) {
            sum = sum - arr[i - cnt] + arr[i];
        }

        // keep track of max length.
        maxcnt = Math.max(cnt, maxcnt);
    }
    return maxcnt;
}

一种有效的方法是使用滑动窗口技术。

  • 遍历数组并检查在添加当前元素时其总和是否小于或等于 k。
  • 如果小于 k,则将其添加到 sum 并增加计数。
  • 其他 删除子数组的第一个元素并减少计数。 再次检查在添加当前元素时其总和是否小于或等于 k。 如果小于 k,则将其添加到 sum 并增加计数。
  • 跟踪最大计数。

这是正确的解决方案。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-08
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多