[刷题] LeetCode 279 Perfect Squares

要求

  • 给出一个正整数n,寻找最少的完全平方数,使他们的和为n

示例

  • n = 12
  • 12 = 4 + 4 + 4
  • 输出:3

边界

  • 是否可能无解?

思路

  • 贪心:12=9+1+1+1,无法得到最优解
  • 图论:从n到0,每个数字表示一个节点,如果两个数字x到y相差一个完全平方数,则连接一条边
  • 问题转化为无权图中从n到0的最短路径

  

实现

 1 class Solution {
 2 public:
 3     int numSquares(int n) {
 4         
 5         assert( n > 0 );
 6         
 7         queue< pair<int,int> > q;
 8         q.push( make_pair( n , 0 ) );
 9         
10         while( !q.empty() ){
11             int num = q.front().first;
12             int step = q.front().second;
13             q.pop();
14             
15             if( num == 0 )
16                 return step;
17                 
18             for( int i = 1 ; num - i*i >=0 ; i ++ )
19                 q.push( make_pair( num - i * i , step + 1 ) );
20         }
21         
22         throw invalid_argument("No Solution");
23     }
24 };
View Code
  • 有些节点被重复推入队列,n足够大时存在性能问题
  • 不同于树,图中每个节点都有多种路径到达
  • 用一个辅助向量记录节点是否推入过队列
  • 优化结束条件
 1 class Solution {
 2 public:
 3     int numSquares(int n) {
 4         
 5         assert( n > 0 );
 6         
 7         queue< pair<int,int> > q;
 8         q.push( make_pair( n , 0 ) );
 9         
10         vector<bool> visited(n+1, false);
11         visited[n] = true;
12         
13         while( !q.empty() ){
14             int num = q.front().first;
15             int step = q.front().second;
16             q.pop();
17             
18             for( int i = 1 ; ; i ++ ){
19                 int a = num - i*i;
20                 if( a < 0 )
21                     break;
22                 if( a == 0)
23                     return step + 1;
24                 if( ! visited[a] ){
25                 q.push( make_pair( a , step + 1 ) );
26                 visited[a] = true;
27             }
28         }
29     }
30     throw invalid_argument("No Solution");
31     }
32 };
View Code

相关

  • 127 Word Ladder
  • 126 Word Ladder II

猜你喜欢

转载自www.cnblogs.com/cxc1357/p/12664376.html