Tree Search(樹狀搜尋)

一、什麼是 Tree Search(樹狀搜尋)? 在人工智慧(AI)與演算法中,許多問題都可以表示成一棵樹(圖一): 起點(A) / | \ B C D /|\ | / \ E F G H I J 每個節點(Node)代表一種狀態(State)。 例如: 迷宮中的位置 棋局的盤面 路徑規劃中的城市 遊戲中的決策 搜尋演算法的目的: 從起點找到目標節點(Goal Node) 二、Breadth First Search (BFS) 核心思想 先搜尋離起點最近的節點。 一層一層往外擴展。 Level 0: A Level 1: B C D Level 2: E F G H I J 搜尋順序: A B C D E F G H I J 圖一結果: A → B → C → D → E → F → G → H → I → J 使用資料結構 Queue(佇列) FIFO: First In First Out 先進先出 例如: Queue: A 取出A 加入B,C,D Queue: B,C,D BFS特性 優點 如果邊權重相同: BFS一定找到最短路徑。 缺點 需要大量記憶體。 假設每個節點有10個子節點: 深度5: 10^5 = 100000 需要保存很多節點。 時間複雜度 O(V + E) V = Vertex(節點數) E = Edge(邊數) 三、Depth First Search (DFS) 核心思想 一路往下走到底。 不能走才回頭。 A | B | E 然後: A | B | F 搜尋順序 圖一結果: A B E F G C H D I J 使用資料結構 Stack(堆疊) LIFO Last In First Out 後進先出 例如: push(B) push(C) push(D) pop() => D DFS特性 優點 記憶體需求小。 只需保存: 目前路徑 即可。 缺點 可能找到很差的解。 例如: A ├── Goal └── 巨大子樹 DFS可能先跑完整個巨大子樹。 時間複雜度 O(V+E)...

LeetCode OJ: 300. Longest Increasing Subsequence 最長遞增子序列


題目連結 https://leetcode.com/problems/longest-increasing-subsequence/,此題用動態規劃解。

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if( nums.size() == 0 ) return 0;

        short *best;
        best = new short[ nums.size() ];
    
        best[0] = 1;
    
        short maxLen = 1;
    
        // Dynamic Programming:
        // if( num[i] > num[k] )
        //   best[i] = max(best[0] ... best[k])
        for( int i = 1; i < nums.size(); i++ )
        {
            short tempBest = 0;
    
            //找出比數字比 num[i] 小且序列長度為最大的值
            for( int k = i - 1; k >= 0; k-- )
            {
                if( nums[i] > nums[k] )
                {
                    if( tempBest < best[k] )
                    {
                        tempBest = best[k];
                    }
                }
            }
    
            best[i] = tempBest + 1;
            if( best[i] > maxLen ) maxLen = best[i];
        }
    
        delete[] best;
        return maxLen;
    }
};

另外若要輸出所找到的最長遞增子序列的話,請參考底下作法:
/*
 Longest Increasing Subsequence
*/
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main( void )
{
  vector<int> num;
  int input;
  short *best;

  while( cin >> input )
  {
    num.push_back( input );
  }

  best = new short[ num.size() ];

  best[0] = 1;

  short maxLen = 1;

  // Dynamic Programming:
  // if( num[i] > num[k] )
  //   best[i] = max(best[0] ... best[k])
  for( int i = 1; i < num.size(); i++ )
  {
    short tempBest = 0;

    //找出比數字比 num[i] 小且序列長度為最大的值
    for( int k = i - 1; k >= 0; k-- )
    {
      if( num[i] > num[k] )
      {
        if( tempBest < best[k] )
        {
          tempBest = best[k];
        }
      }
    }

    best[i] = tempBest + 1;
    if( best[i] > maxLen ) maxLen = best[i];
  }

  vector<int>* subSet = new vector<int>[ maxLen ];

  for( int i = 0; i < num.size(); i++ )
  {
    //cout << best[i] << " ";
    subSet[ best[i] - 1].push_back( num[i] );
  }

  cout << endl << endl;
  for( int i = 0; i + 1 < maxLen; i++ )
  {
    sort( subSet[i].begin(), subSet[i].end() );

    int max = 0;
    for( int j = 0; j < subSet[i].size(); j++ )
      if( (subSet[i])[j] < (subSet[i+1])[subSet[i+1].size() - 1] && max < (subSet[i])[j])
      {
        max = (subSet[i])[j];

      }
      cout << max << " ";
  }

  cout << (subSet[maxLen - 1])[0] << endl;


  delete[] best;
  delete[] subSet;
  return 0;
}
若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。

留言

這個網誌中的熱門文章