查看: 15961| 回复: 24
跳转到指定楼层
上一主题 下一主题
收起左侧

Google : 求最长等差数列

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
给定一个未排序数组,找出其中最长的等差数列.

(PS O(n^2)的时间复杂度,这题如果能自己作出来相当不容易)

上一篇:Microsoft : 找出唯一重复的数
下一篇:Google : Find Fibonacci combinations
推荐
梦流星 2015-6-30 20:29:49 | 只看该作者
全局:
已经AC了, 把自己的代码贴上来, 这个地方需要自己写个哈希, 系统自带的__gnu_cxx::hash_map要快于unordered_map, 但是还是tle,
自己写的则快很多:

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <map>
  7. #include <unordered_map>
  8. #include <unordered_set>
  9. #include <ext/hash_map>

  10. using namespace std;
  11. using __gnu_cxx::hash_map;

  12. int n;
  13. int a[10001];

  14. const int BUCKET_SIZE   = 42839;
  15. const int NEXT_POS      = 7;

  16. typedef struct _my_hash
  17. {
  18.     int _bucket[BUCKET_SIZE];
  19.     int _key[BUCKET_SIZE];
  20.     _my_hash()
  21.     {
  22.         memset(_bucket, 0, sizeof(_bucket[0]) * BUCKET_SIZE);
  23.         memset(_key, 0, sizeof(_key[0]) * BUCKET_SIZE);
  24.     }
  25.     void insert(int key, int value)
  26.     {
  27.         int mod = key % BUCKET_SIZE;
  28.         while (_key[mod] != 0)
  29.         {
  30.             mod = (mod + NEXT_POS) % BUCKET_SIZE;
  31.         }
  32.         _bucket[mod]    = value;
  33.         _key[mod]       = key;
  34.     }
  35.     int find(int key)
  36.     {
  37.         int origin = key % BUCKET_SIZE;
  38.         int mod = key % BUCKET_SIZE;
  39.         while (_key[mod] != 0)
  40.         {
  41.             if (_key[mod] == key)
  42.             {
  43.                 return _bucket[mod];
  44.             }
  45.             mod = (mod + NEXT_POS) % BUCKET_SIZE;
  46.             if (mod == origin)
  47.             {
  48.                 return -1;
  49.             }
  50.         }
  51.         return -1;
  52.     }
  53. }my_hash_t;

  54. //let's assume that sequence s(n) = a[i] s(n+1) = a[j]
  55. //dp_matrix[i][j] represent the count of sequence in s
  56. short int dp_matrix[10001][10001];

  57. int main()
  58. {
  59.     //cin >> n;
  60.     scanf("%d", &n);
  61.     for (int i = 0; i < n; ++i)
  62.         //cin >> a[i];
  63.         scanf("%d", &a[i]);
  64.     sort(&a[0], &a[n]);
  65.     //unordered_map<int, int> element_map;
  66.     //map<int, int> element_map;
  67.     //hash_map<int, int> element_map(42839);
  68.     my_hash_t my_hash;
  69.     //hash_map<int, int> element_map;
  70.     for (int i = 0; i < n; ++i)
  71.     {
  72.         //element_map[a[i]] = i;
  73.         my_hash.insert(a[i], i);
  74.     }
  75.     memset(dp_matrix, 0, sizeof(dp_matrix[0][0]) * 10001 * 10001);
  76.     short int max_len = 0;
  77.     //const auto iter_end = element_map.end();

  78.     for (int i = 0; i < n; ++i)
  79.     {
  80.         for (int j = i + 1; j < n; ++j)
  81.         {
  82.             int cur_delta = a[j] - a[i];
  83.             int k_value = a[i] - cur_delta;
  84.             //auto iter = element_map.find(k_value);
  85.             //auto iter = element_map.end();
  86.             int ret = my_hash.find(k_value);
  87.             //if (iter != iter_end)
  88.             if (ret != -1)
  89.             {
  90.                 //dp_matrix[i][j] = dp_matrix[iter->second][i] + 1;
  91.                 dp_matrix[i][j] = dp_matrix[ret][i] + 1;
  92.             }
  93.             else
  94.             {
  95.                 dp_matrix[i][j] = 2;
  96.             }
  97.             if (dp_matrix[i][j] > max_len)
  98.             {
  99.                 max_len = dp_matrix[i][j];
  100.             }
  101.         }
  102.     }
  103.     cout << max_len << endl;
  104.     return 0;
  105. }
复制代码
回复

使用道具 举报

推荐
梦流星 2015-6-30 10:59:32 | 只看该作者
全局:
本帖最后由 梦流星 于 2015-6-30 11:02 编辑

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstring>

  4. using namespace std;

  5. int n;
  6. int a[10001];

  7. //let's assume that sequence s(n) = a[i] s(n+1) = a[j]
  8. //dp_matrix[i][j] represent the count of sequence in s
  9. short int dp_matrix[10001][10001];

  10. int main()
  11. {
  12.     cin >> n;
  13.     for (int i = 0; i < n; ++i)
  14.         cin >> a[i];
  15.     memset(dp_matrix, 0, sizeof(dp_matrix[0][0]) * 10001 * 10001);
  16.     short int max_len = 0;

  17.     for (int i = 0; i < n; ++i)
  18.     {   
  19.         for (int j = i + 1; j < n; ++j)
  20.         {   
  21.             bool delta_is_match = false;
  22.             int cur_delta = a[j] - a[i];
  23.             for (int k = i-1; k >= 0; --k)
  24.             {   
  25.                 int delta_i_to_k = a[i] - a[k];
  26.                 if (delta_i_to_k == cur_delta)
  27.                 {   
  28.                     if (dp_matrix[i][j] < dp_matrix[k][i] + 1)
  29.                         dp_matrix[i][j] = dp_matrix[k][i] + 1;
  30.                     else
  31.                         cout << "k:" << k << " i:" << i << " j:" << j << endl;
  32.                     delta_is_match = true;
  33.                     break;
  34.                 }   
  35.             }   
  36.             if (delta_is_match == false)
  37.             {   
  38.                 dp_matrix[i][j] = 2;
  39.             }   
  40.             if (dp_matrix[i][j] > max_len)
  41.             {   
  42.                 max_len = dp_matrix[i][j];
  43.             }   
  44.         }   
  45.     }   
  46.     //for_each(&dp_matrix[0], &dp_matrix[n], [=](short int p[]){for_each(&p[0], &p[n],[](short int n){cout<<n<<' ';});cout<<endl;});
  47.     cout << max_len << endl;
  48.     return 0;
  49. }
复制代码
我的代码我觉得应该是对的  但是wa, 我还在想为什么..我算出来的结果比正确结果低  有一个正确结果是25  我算出来是7....
回复

使用道具 举报

推荐
梦流星 2015-6-30 16:55:46 | 只看该作者
全局:


  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <unordered_map>
  7. #include <unordered_set>

  8. using namespace std;

  9. int n;
  10. int a[10001];

  11. //let's assume that sequence s(n) = a[i] s(n+1) = a[j]
  12. //dp_matrix[i][j] represent the count of sequence in s
  13. short int dp_matrix[10001][10001];

  14. int main()
  15. {
  16.     //cin >> n;
  17.     scanf("%d", &n);
  18.     for (int i = 0; i < n; ++i)
  19.         //cin >> a[i];
  20.         scanf("%d", &a[i]);
  21.     sort(&a[0], &a[n]);
  22.     unordered_map<int, int> element_map;
  23.     for (int i = 0; i < n; ++i)
  24.     {   
  25.         element_map[a[i]] = i;
  26.     }   
  27.     memset(dp_matrix, 0, sizeof(dp_matrix[0][0]) * 10001 * 10001);
  28.     short int max_len = 0;
  29.     const auto iter_end = element_map.end();

  30.     for (int i = 0; i < n; ++i)
  31.     {   
  32.         for (int j = i + 1; j < n; ++j)
  33.         {   
  34.             int cur_delta = a[j] - a[i];
  35.             int k_value = a[i] - cur_delta;
  36.             auto iter = element_map.find(k_value);
  37.             if (iter != iter_end)
  38.             {   
  39.                 dp_matrix[i][j] = dp_matrix[iter->second][i] + 1;
  40.             }   
  41.             else
  42.             {   
  43.                 dp_matrix[i][j] = 2;
  44.             }   
  45.             if (dp_matrix[i][j] > max_len)
  46.             {   
  47.                 max_len = dp_matrix[i][j];
  48.             }   
  49.         }   
  50.     }   
  51.     cout << max_len << endl;
  52.     return 0;
  53. }

复制代码
这个代码还是tle了  实在过不去了~~~~ 咋办?
回复

使用道具 举报

🔗
epic 2011-7-28 15:34:02 | 只看该作者
全局:
平方的算法应该还是不难的吧?
首先做一个hash表,维护key={a,b} value=c,含义是以a开始的差为b的等差数列,最长为c
查找更新都是O(1)

然后两层循环,第一层for (int i=n-1;i>=0;--i)枚举数列头
第二层for (int j=i+1;j<n;++j)枚举数列第二项
在hash表里查找num[i],num[j]-num[i]并将其值更新
回复

使用道具 举报

🔗
 楼主| wwwyhx 2011-7-28 16:00:01 | 只看该作者
全局:
平方的算法应该还是不难的吧?
首先做一个hash表,维护key={a,b} value=c,含义是以a开始的差为b的等差数列,最长为c
查找更新都是O(1)

然后两层循环,第一层for (int i=n-1;i>=0;--i)枚举数列头
第二层for (int j=i+1;j
epic 发表于 2011-7-28 15:34



    哈哈,不错啊,这样做hash, 不过hash一般是万能解法......
回复

使用道具 举报

🔗
darksteel 2011-7-29 13:06:14 | 只看该作者
全局:
本帖最后由 darksteel 于 2011-7-29 13:08 编辑

回复 3# wwwyhx
  1. #define MAXL 1000
  2. int find(int a[], int n)
  3. {
  4.         int dp[MAXL][MAXL];
  5.         int i, j;
  6.         for(i = 1; i < n; i++) {
  7.                 int p = 0;
  8.                 for(j = 0; j < i; j++) {
  9.                         dp[j][i] = 2;
  10.                         while(p < j && a[p] + a[i] < 2 * a[j])
  11.                                 p++;
  12.                         if(p < j && a[p] + a[i] == 2 * a[j])
  13.                                 dp[j][i] = max(dp[j][i], dp[p][j] + 1);
  14.                 }
  15.         }
  16.         int ans = (n > 0);
  17.         for(i = 1; i < n; i++)
  18.                 for(j = 0; j < i; j++)
  19.                         ans = max(ans, dp[j][i]);
  20.         return ans;

  21. }
复制代码
不用hash应该也能做,思路也是dp。dp[j][ i ]表示以a[j]和a[ i ]结尾的最长等差数列的长度。枚举最后两个元素,对于每一个a[j]和a[ i ],都要找到a[p],p < j,满足a[p] + a[ i ] == 2 * a[j]。然后dp[p][j] + 1去更新dp[j][ i ]。看起来是三层循环,但其实对于同一个i,p的位置是随着j增大而增大的,所以最里面的while循环对于每个i值最多是O(n)的代价。总的代价还是O(n^2)。
回复

使用道具 举报

🔗
darksteel 2011-7-29 13:11:25 | 只看该作者
全局:
不过我这个好像要升序的数组才行。。{:4_84:}
回复

使用道具 举报

🔗
 楼主| wwwyhx 2011-7-30 09:17:41 | 只看该作者
全局:
本帖最后由 wwwyhx 于 2011-7-30 09:22 编辑
回复  wwwyhx 不用hash应该也能做,思路也是dp。dp[j][ i ]表示以a[j]和a[ i ]结尾的最长等差数列的长度。枚举最后两个元素,对于每一个a[j]和a[ i ],都要找到a,p < j,满足a + a[ i ] == 2 * a[j]。然后dp[j] + 1去更新dp[j][ i ]。看起来是三层循环,但其实对于同一个i,p的位置是随着j增大而增大的,所以最里面的while循环对于每个i值最多是O(n)的代价。总的代价还是O(n^2)。
darksteel 发表于 2011-7-29 13:06



    p++没道理,升序也不成
回复

使用道具 举报

🔗
darksteel 2011-7-30 12:47:34 | 只看该作者
全局:
回复 6# wwwyhx
没有吧,升序的话应该是可以的,如果a[p]、a[j]、a[ i ]和a[q]、a[j+1]、a[ i ]分别构成等差数列,由于a[j+1]>a[j],所以有a[q]>a[p]。所以对于同一个i,随着j的增加,能够与a[j]、a[ i ]构成等差数列的a[p]肯定是不断增大的。
回复

使用道具 举报

🔗
 楼主| wwwyhx 2011-7-30 15:14:17 | 只看该作者
全局:
回复  wwwyhx
没有吧,升序的话应该是可以的,如果a、a[j]、a[ i ]和a[q]、a[j+1]、a[ i ]分别构成等差数列,由于a[j+1]>a[j],所以有a[q]>a。所以对于同一个i,随着j的增加,能够与a[j]、a[ i ]构成等差数列的a肯定是不断增大的。
darksteel 发表于 2011-7-30 12:47



    恩,是对的,你还真想的到.
    还有一种DP的就是:
    假设在升序数组里,由n...1对每个数x,两边扩展求a,b,使得x-a == b-x,这样f(b,x) = f(x,a)+1
回复

使用道具 举报

🔗
swordsnow 2011-9-5 11:08:38 | 只看该作者
全局:
楼主看看这个方法对不对;
用dp[i][dif] 表示以a[i]结尾,差为dif的等差数列长度最大值;
memset(dp,0,sizeof(dp));
for (i=2;i<=n;i++)
  for (j=1;j<=i-1;j++)
{
       int temp;
       if (a[i]-a[j]<0)  temp=base+(a[i]-a[j]);  //是负数给它加上个base (更好的办法时将差hash到一个数组中)
       else temp=a[i]-a[j];
       dp[i][temp]=max(dp[j][temp]+1,dp[i][temp]);
       ans=max(ans,dp[i][temp]);     
}
回复

使用道具 举报

🔗
 楼主| wwwyhx 2011-9-5 11:25:56 | 只看该作者
全局:
楼主看看这个方法对不对;
用dp[dif] 表示以a结尾,差为dif的等差数列长度最大值;
memset(dp,0,sizeof(dp));
for (i=2;i
swordsnow 发表于 2011-9-5 11:08


空间复杂度太高,我记得这种伪DP都是NP问题没办法了才用的
回复

使用道具 举报

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

本版积分规则

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