zoukankan      html  css  js  c++  java
  • Daliy Algorithm (dp,堆)-- day 79

    Nothing to fear


    种一棵树最好的时间是十年前,其次是现在!

    那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~

    2020.5.15


    人一我十,人十我百,追逐青春的梦想,怀着自信的心,永不言弃!

    Constructing the Array

    构造算法,和优先队列得使用,优先队列好久不用都有点忘记了,回头总结什么时候用优先队列比较合适。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <cassert>
    #include <string>
    #include <iomanip>
    #include <cmath>
    #include <ctime>
    #include <queue>
    #define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    #define lowbit(x) (x & -x)
    using namespace std;
    typedef long long ll;
    const int MAX = 0x7ffffff;
    int t;
    
    struct node{
        int l , r , len;
        bool operator < (const node &x) const 
        {
            if(len == x.len)return l > x.l;
            else return len < x.len;
        } 
    };
    
    void slove()
    {
        int n;
        cin >> n;
        vector<int> a(n + 1);
        priority_queue<node> q;
        q.push({1 , n , n});
        int val = 1;
        while(!q.empty())
        {
            node now = q.top();
            //printf("now segment : [%d,%d]
    ",now.l,now.r);
            q.pop();
            int k = now.r - now.l + 1;
            int mid = 0;
            if(k % 2 != 0)
            {
                mid = now.l + now.r >> 1;
                a[mid] = val;
            }else {
                mid = now.l + now.r - 1  >> 1;
                a[mid] = val;
            }
            //printf("left :[%d,%d] right[%d,%d]
    ",now.l,mid-1,mid+1,now.r);
            int l = now.l, r = mid - 1;
            if(l <= r)q.push({now.l , mid-1,mid - now.l});
            l = mid + 1,r = now.r;
            if(l <= r)q.push({mid + 1,now.r , now.r - mid});
            val++;
        }
        for(int i = 1;i <= n ;i ++) cout << a[i] << " ";
        cout << endl;
        return ;
    }
    int main()
    {
    #ifdef LOCAL
        auto start_time = clock();
        cerr << setprecision(3) << fixed; // 在iomanip中
    #endif
        SIS;
        cin >> t;
        while(t--)
        {
            slove();
        }
    #ifdef LOCAL
        auto end_time = clock();
        cerr << "Execution time: " << (end_time - start_time) * (int)1e3 / CLOCKS_PER_SEC << " ms
    ";
    #endif
    }
    

    LC-91 解码方法

    变种斐波那契问题 ,边界问题考虑情况比较多。

    总结: 要考虑的几个点

    1. 首先如果是 0 开头的则一定无法进行转码
    2. f[0] = 1
    3. 判定第二个位置的取值情况
      如果 s[0] + s[1] <= 26 :
      如果 s[1] == 0 则只有 10 / 20 两种情况
      故 f[1] = 1
      否则 可以构成两种转码 f[1] = 2
      否则 :
      如果 s[1] == 0 : 40 / 50...等情况
      f[1] = 0
      否则 其单独构成一个码
      f[1] = 1
    4. 从第三位开始:
    // 如果当前位是 0 且前一位不是 1 且不是 2 那么一定不能解码成功例如00 30 故无法再往下进行
    if(s[i-1] != '1' && s[i-1] != '2') 
    {  
        if(s[i] == '0')return 0;
        // 如果当前不是 可以当作是单个进行解码 32 45... 
        else f[i] = f[i-1];
    }else {
        // 如果确保前一位是 1 或者 2 
        // 如果当前位是0 或者即只能构成 10 / 20故要从 f[i-2]进行转移
        if(s[i] == '0')f[i] = f[i-2];
        else {
            // 否则普通的情况是s[i-1] + s[i] <= 26 可以由 f[i-1] + f[i-2]转移
            if(s.substr(i-1,2) <= "26")
            {
                f[i] = f[i-1] + f[i-2];
            }else f[i] = f[i-1];
            // 否则只能进行单词拆分解码
        }
    } 
    
    class Solution {
    public:
        int numDecodings(string s) {
            int n = s.length();
            if(s[0] == '0')return 0;
            if(n == 1)return 1;
    
            vector<int> f(n , 0);
            f[0] = 1;
            if(s.substr(0 , 2) <= "26")
                 f[1] = s[1] == '0' ? 1 : 2;
            else f[1] = s[1] == '0' ? 0 : 1;
            for(int i = 2;i < n ;i ++)
            {
                if(s[i-1] != '1' && s[i-1] != '2') 
                // 如果当前位是 0 且前一位不是 1 且不是 2 那么一定不能解码成功例如00 30
                // 故无法再往下进行
                {  
                    if(s[i] == '0')return 0;
                    // 如果当前不是 可以当作是单个进行解码 32 45... 
                    else f[i] = f[i-1];
                }else {
                    // 如果确保前一位是 1 或者 2 
                    // 如果当前位是0 或者即只能构成 10 / 20故要从 f[i-2]进行转移
                    if(s[i] == '0')f[i] = f[i-2];
                    else {
                        // 否则普通的情况是s[i-1] + s[i] <= 26 可以由 f[i-1] + f[i-2]转移
                        if(s.substr(i-1,2) <= "26")
                        {
                            f[i] = f[i-1] + f[i-2];
                        }else f[i] = f[i-1];
                        // 否则只能进行单词拆分解码
                    }
                } 
            }
            return f[n-1];
        }
    };
    

    lc-516. 最长回文子序列

    对于子序列问题的通用模型就差不多是这种,但是迭代形式多种多样,由从上往下,也有从下至上,还有斜着更新状态的

    状态的选定是解决dp问题的一大关键:

    状态表示:
    f[i][j] : 从 i - j 中的的最长回文子序列的最大长度

    状态计算:

    1. f[i][i] = 1;
    2. 当 a[i] == a[j] :
      f[i][j] = f[i+1][j-1] + 2
      否则 f[i][j] = max(f[i+1][j],f[i][j-1])
      for( i )
      for (j)
      if(a[i] == a[j]):
      ...
      else ...
    class Solution {
    public:
        int longestPalindromeSubseq(string s) {
            int n = s.size();
            vector<vector<int>> f(n , vector<int> (n , 0));
            // 每一个字串都是一个回文子序列
            for(int i = 0;i < n ;i ++)f[i][i] = 1;
    
            for(int i = n - 1;i >= 0; i--)
            {
                for(int j = i + 1;j < n ;j ++)
                {
                    if(s[i] == s[j])
                    {
                        f[i][j] = f[i+1][j-1] + 2;
                    }else{
                        f[i][j] = max(f[i+1][j],f[i][j-1]);
                    }
                }
            }
            return f[0][n-1];
        }
    };
    
  • 相关阅读:
    KY2成绩排序
    python 获取list中元素的索引
    pandas 读取指定一列数据
    python 删除列表中的第一位元素
    python 时间戳
    python 除法保留小数点后两位
    python 读取excel表格的一列数据并去重
    python中获取Excel表格sheet页整页内容
    IDEA创建spring boot项目
    servlet一些问题
  • 原文地址:https://www.cnblogs.com/wlw-x/p/12896983.html
Copyright © 2011-2022 走看看