楼主: zhenjieruan
跳转到指定楼层
上一主题 下一主题
收起左侧

Facebook二面跪经。。。

🔗
tk1322715 2016-3-15 07:31:31 | 只看该作者
全局:
zhenjieruan 发表于 2016-3-15 07:14
我理解0-x应该怎么做,但是x-size应该怎么做呢?是分治吗?

你设一个y,从x-size跑一遍,算出从x-y最大的n个连续数的和。然后让y从size-x倒着跑一遍算出y-size之间最大的n个连续数的和。然后再正向跑一遍得到y左边和右边加起来最大的和。总共跑了三遍。所以是o(n)
回复

使用道具 举报

🔗
 楼主| zhenjieruan 2016-3-15 07:35:39 | 只看该作者
全局:
tk1322715 发表于 2016-3-15 07:31
你设一个y,从x-size跑一遍,算出从x-y最大的n个连续数的和。然后让y从size-x倒着跑一遍算出y-size之间最 ...

ok ok,让我想起了programming pearl里的一个算法,谢谢大神了!
回复

使用道具 举报

🔗
 楼主| zhenjieruan 2016-3-15 07:36:46 | 只看该作者
全局:
tk1322715 发表于 2016-3-15 07:31
你设一个y,从x-size跑一遍,算出从x-y最大的n个连续数的和。然后让y从size-x倒着跑一遍算出y-size之间最 ...

Sorry,如果问题有点多。。这个x和y怎么选择?是选k吗?肯定得比k大吧
回复

使用道具 举报

🔗
tk1322715 2016-3-15 07:42:09 | 只看该作者
全局:
zhenjieruan 发表于 2016-3-15 07:36
Sorry,如果问题有点多。。这个x和y怎么选择?是选k吗?肯定得比k大吧

大概就是x从0到size, y就是从x到size. 真正写的话还有corner case,具体的值就得看你是怎么实现的了。
回复

使用道具 举报

🔗
novice00 2016-3-15 07:42:27 | 只看该作者
全局:
分享一个我的想法,用的是dp, 可以把3换成其他数字,时间复杂度 3*n,空间3*n,但是空间可以优化到n
    int maxSum(int[] array, int n) {
        int len = array.length;
        //sum[i] 是数组 array[i] 到 array[i+n-1] 的和
        int[] sum = new int[len - n + 1];
        int curSum = 0;
        for (int i = 0; i < len; i++) {
            if (i < n - 1) curSum += array[i];
            else {
                curSum += array[i];
                sum[i - n + 1] = curSum;
                curSum -= array[i - n + 1];
            }
        }
        int[][] dp = new int[3][sum.length];
        /*
         * dp[i][j] 的意思是,sum[j]之前的i个不overlap的n个array中连续数字的
         * 最大和+sum[j],所以basecase dp[0]就是sum数组本身
         */
        for (int i = 0; i < sum.length; i++) {
            dp[0][i] = sum[i];
        }
      
        for (int i = 1; i < 3; i++) {
            int curMax = 0;
            for (int j = 0; j < sum.length; j++) {
                if (j - i * n < 0) continue;
                curMax = curMax > dp[i-1][j - i * n] ? curMax : dp[i-1][j - i * n];
                dp[i][j] = curMax + sum[j];
            }
        }
        int max = 0;
        for (int j = 0; j < sum.length; j++) {
            max = max > dp[2][j] ? max : dp[2][j];
        }
        return max;
    }

代码写的匆忙可能有bug,欢迎大家讨论
回复

使用道具 举报

🔗
guschen802 2016-3-15 08:28:12 | 只看该作者
全局:
這是我的想法,應該和他說的差不多吧@tk1322715, 簡單來說就是3個windows。我以中間的window為基準,往右滑動保持windows的合,然後,每次滑動,左右各用第一題的算法找出左邊最大以及右邊最大的windows合,3個相加后維護最大值,代碼如下:

  1. import java.util.*;
  2. public class Solution {
  3.     public static void main(String[] args) {
  4.         int[] nums = new int[]{1,3,7,7,2,1,1,4,8,8,6,1,1,9};
  5.         System.out.println(maxThreeWindowSum(nums,2));
  6.     }

  7.     public static int maxWindowSum(int[] nums, int start, int end, int n) {
  8.         if (nums == null || end - start+1 < n) throw new IllegalArgumentException();
  9.         int sum = 0;
  10.         int max = Integer.MIN_VALUE;
  11.         Queue<Integer> window = new LinkedList<>();
  12.         for (int i = start; i <= end ; i++) {
  13.             if(window.size() < n-1) {
  14.                 sum+=nums[i];
  15.                 window.offer(nums[i]);
  16.             } else {
  17.                 sum+=nums[i];
  18.                 window.offer(nums[i]);
  19.                 max = Math.max(max,sum);
  20.                 sum-=window.poll();
  21.             }
  22.         }
  23.         return max;
  24.     }

  25.     public static int maxThreeWindowSum(int[] nums, int n) {
  26.         if (nums == null || nums.length < 3*n) throw new IllegalArgumentException();
  27.         //move the window in the middle and find max window at both side;
  28.         int max = Integer.MIN_VALUE;
  29.         int middle = 0;
  30.         Queue<Integer> window = new LinkedList<>();
  31.         for (int i = n; i < nums.length-2*n; i++) {

  32.             if(window.size() < n-1) {
  33.                 middle+=nums[i];
  34.                 window.offer(nums[i]);
  35.             } else {
  36.                 middle+=nums[i];
  37.                 window.offer(nums[i]);
  38.                 int left = maxWindowSum(nums, 0, i-n, n);
  39.                 int right = maxWindowSum(nums, i+1, nums.length -1, n);
  40.                 max = Math.max(max, left + middle + right);
  41.                 middle-=window.poll();
  42.             }
  43.         }
  44.         return max;
  45.     }
  46. }
复制代码


补充内容 (2016-3-15 08:29):
時間應該是O(n^2)

补充内容 (2016-3-15 08:36):
33筆誤,應為i < nums.length -n;
回复

使用道具 举报

🔗
tk1322715 2016-3-15 08:34:48 | 只看该作者
全局:
novice00 发表于 2016-3-15 07:42
分享一个我的想法,用的是dp, 可以把3换成其他数字,时间复杂度 3*n,空间3*n,但是空间可以优化到n
     ...

层主看了你的答案。我感觉可能有点不对的地方。
curMax = curMax > dp[i-1][j - i * n] ? curMax : dp[i-1][j - i * n];
dp[i][j] = curMax + sum[j];
这两行代买我有点疑惑。
根据你的定义,dp[i-1][j - i * n] =sum[j - i * n]之前的i个不overlap的n个array中连续数字的最大和 + sum(j - i*n);
那这个sum(j- i * n) 所代表的连续n个数可能和后面的sum(j)重合。然后你之后dp[i][j]又加一次sum[j]。我感觉就有可能加错了。
回复

使用道具 举报

🔗
tk1322715 2016-3-15 08:40:41 | 只看该作者
全局:
guschen802 发表于 2016-3-15 08:28
這是我的想法,應該和他說的差不多吧@tk1322715, 簡單來說就是3個windows。我以中間的window為基準,往右 ...

厉害厉害。哈哈,感觉这道题能有leetcode的hard里偏简单的。而且实现起来可能还有很多小技巧。不然的话代码可能会很乱。
回复

使用道具 举报

🔗
guschen802 2016-3-15 09:00:56 | 只看该作者
全局:
tk1322715 发表于 2016-3-15 08:40
厉害厉害。哈哈,感觉这道题能有leetcode的hard里偏简单的。而且实现起来可能还有很多小技巧。不然的话代 ...

我覺得還能再優化,每次左右都有重複的搜索,如果能保存歷史的話,例如左邊,每多一個數字,組成一個新的window,和歷史最大比就好,不用從頭開始掃..不過想想就覺得有點複雜
回复

使用道具 举报

🔗
wtcupup 2016-3-15 09:15:07 | 只看该作者
全局:
guschen802 发表于 2016-3-15 09:00
我覺得還能再優化,每次左右都有重複的搜索,如果能保存歷史的話,例如左邊,每多一個數字,組成一個新的 ...

请问你的代码第41行,求i左边的maxWindowSum为什么不是i-1而是i-n?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表