StoneMerge

今天搞了一天石子合并

几个版本

直接循环数组,每次O(n^3), 总时间O(n^4),复杂度太高了

#include <cstdio>  
#include <algorithm>  
using namespace std;  
int dp[1000][1000];  
int a[1000],n;  
int stonemax()  
{  
    for(int i=0;i<=n-1;i++)  
        dp[i][i]=0;  
    for(int len=2;len<=n;len++)  
    {  
        for(int i=0;i<n;i++)  
        {  
            int j=i+len-1;  
            if(j>=n)  
                break;  
            //int maxn=0,minn=0x7fffffff;  
            int sum=0;for(int l=i;l<=j;l++)sum+=a[l];  
            int maxn=dp[i][i]+dp[i+1][j]+sum;  
            for(int k=i+1;k<=j-1;k++)  
            {  
                maxn=max(maxn,dp[i][k]+dp[k+1][j]+sum);  
            }  
            dp[i][j]=maxn;  
        }  
    }  
    return dp[0][n-1];  
}  

int stonemin()  
{  
    for(int i=0;i<=n-1;i++)  
        dp[i][i]=0;  
    for(int len=2;len<=n;len++)  
    {  
        for(int i=0;i<n;i++)  
        {  
            int j=i+len-1;  
            if(j>=n)  
                break;  
            //int maxn=0,minn=0x7fffffff;  
            int sum=0;for(int l=i;l<=j;l++)sum+=a[l];  
            int minn=dp[i][i]+dp[i+1][j]+sum;  
            for(int k=i+1;k<=j-1;k++)  
            {  
                minn=min(minn,dp[i][k]+dp[k+1][j]+sum);  
            }  
            dp[i][j]=minn;  
        }  
    }  
    return dp[0][n-1];  
}  

int main()  
{  
    freopen("in.txt","r",stdin);  
    while(scanf("%d",&n)!=EOF)  
    {  
        for(int i=0;i<n;i++)  
            scanf("%d",&a[i]);  
        int tmp,maxn=stonemax(),minn=stonemin();  
        for(int loop=1;loop<n;loop++)  
        {  
            tmp=a[0];  
            for(int i=0;i<n-1;i++)  
                a[i]=a[i+1];  
            a[n-1]=tmp;  
            maxn=max(maxn,stonemax());  
            minn=min(minn,stonemin());  
        }  
        printf("%d %d\n",minn,maxn);  
    }  
}

扩展数组,然后DP状态扩大,空间扩了一倍,编程复杂度后面的低,时间O(n^3)
然后一直出了一个问题,就是i没有扩展到0-2n-1, 因为后面的子问题状态可能起点会 n-2n-1的范围里,一直都没有想到这个点。这里还要感谢瞿神

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
int dp[1000][1000];
int a[1000],n;
int stonemax()
{
    for(int i=0; i<=n-1; i++)
        dp[i] [i] =0;
    for(int len=2; len<=n; len++)
    {
        for(int i=0; i<n; i++)
        {
            int j=i+len-1;
            if(j>=n)
                break;
            int sum=0;
            for(int l=i; l<=j; l++)sum+=a[l] ;
            int maxn=dp[i] [i] +dp[i+1][j] +sum;
            for(int k=i+1; k<=j-1; k++)
            {
                maxn=max(maxn,dp[i] [k] +dp[k+1][j] +sum);
            }
            dp[i] [j] =maxn;
        }
    }
    return dp[0][n-1];
}
int stonemin()
{
    for(int i=0; i<=n-1; i++)
        dp[i] [i] =0;
    for(int len=2; len<=n; len++)
    {
        for(int i=0; i<n; i++)
        {
            int j=i+len-1;
            if(j>=n)
                break;
            int sum=0;
            for(int l=i; l<=j; l++)sum+=a[l] ;
            int minn=dp[i] [i] +dp[i+1][j] +sum;
            for(int k=i+1; k<=j-1; k++)
            {
                minn=min(minn,dp[i] [k] +dp[k+1][j] +sum);
            }
            dp[i] [j] =minn;
        }
    }
    return dp[0][n-1];
}
int stonemax_mod()
{
    for(int i=0; i<=n-1; i++)
        dp[i] [i] =0;
    for(int len=2; len<=n; len++)
    {
        for(int i=0; i<=n-1; i++)
        {
            int j=(i+len-1)%n;
            int sum=0;
            if(i<j)
            {
                for(int l=i; l<=j; l++)sum+=a[l] ;
            }
            else
            {
                for(int l=i; l<=n-1; l++)sum+=a[l] ;
                for(int l=0; l<=j; l++)sum+=a[l] ;
            }
            int maxn=0;
            if(i<j)
            {
                for(int k=i; k<=j-1; k++)
                    maxn=max(maxn,dp[i] [k] +dp[k+1][j] +sum);
            }
            else
            {
                for(int k=i; i<=n-1; i++)
                    maxn=max(maxn,dp[i] [k] +dp[k+1][j] +sum);
                for(int k=0; k<=j-1; k++)
                    maxn=max(maxn,dp[i] [k] +dp[k+1][j] +sum);
            }
            dp[i] [j] =maxn;
        }
    }
    int maxn=0;
    for(int i=0; i<=n-1; i++)
        maxn=max(maxn,dp[i] [(i-1+n)%n]);
    return maxn;
}
int stonemax_extendarray()
{
    for(int i=0; i<=n-1; i++)
        dp[i] [i] =0,a[n+i]=a[i] ;
    int maxs=0;
    for(int len=2; len<=n; len++)
    {
        for(int i=0; i<2*n; i++)
        {
            int j=i+len-1;
            if(j>=2*n) break;
            int sum=0;
            for(int l=i; l<=j; l++)sum+=a[l] ;
            int maxn=0;
            for(int k=i; k<=j-1; k++)
            {
                maxn=max(maxn,dp[i] [k] +dp[k+1][j] +sum);
            }
            dp[i] [j] =maxn;
        }
    }
    for(int i=0; i<n; i++)maxs=max(maxs,dp[i] [n-1+i]);
    return maxs;
}
int stonemin_extendarray()
{
    for(int i=0; i<=n-1; i++)
        dp[i] [i] =0,a[n+i]=a[i] ;
    int mins=0x7fffffff;
    for(int len=2; len<=n; len++)
    {
        for(int i=0; i<2*n; i++)
        {
            int j=i+len-1;
            if(j>=2*n)break;
            int sum=0;
            for(int l=i; l<=j; l++)sum+=a[l] ;
            int minn=0x7fffffff;
            for(int k=i; k<=j-1; k++)
            {
                minn=min(minn,dp[i] [k] +dp[k+1][j] +sum);
            }
            dp[i] [j] =minn;
        }
    }
    for(int i=0; i<n; i++)mins=min(mins,dp[i] [n-1+i]);
    return mins;
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0; i<n; i++)
            scanf("%d",&a[i] );
        int tmp,minn=stonemin_extendarray(),maxn=stonemax_extendarray();
        printf("%d %d\n",minn,maxn);
    }
}

不取模,空间压缩了,也是O(n^3),空间降了,伟哥的代码

#include <iostream>
#include <vector>
#include <fstream>
using namespace std;

const int MAXINT = 2147483647;

struct MinSum{
public:
    int get_min_score(vector<int> const &stones){
        vector<int> sum(stones.size(), 0);
        vector<vector<int> > dp(stones.size(), sum);
        sum[0] = stones[0];
        for (int i = 1; i < stones.size(); ++ i)sum[i] = sum[i - 1] + stones[i];
        for (int j = 1; j < stones.size(); ++ j){
            for (int i = 0; i < stones.size(); ++ i){
                dp[i][j] = MAXINT;
                for (int k = 0; k <j; ++ k){
                    int cur_temp = dp[i][k] + dp[(i + k + 1) % stones.size()][j - k - 1];
                    dp[i][j] = (dp[i][j] > cur_temp ? cur_temp : dp[i][j]);
                }
                int tail_index = (i + j) % stones.size();
                int cur_sum_temp = 0;
                if (tail_index > i)cur_sum_temp = sum[tail_index] - (i == 0 ? 0 : sum[i - 1]);
                else cur_sum_temp = sum[sum.size() - 1] - (i == 0 ? 0 : sum[i - 1]) + sum[tail_index];
                dp[i][j] += cur_sum_temp;
            }
        }
        int result = dp[0][stones.size() - 1];
        for (int i = 1; i < stones.size(); ++ i)result = (result < dp[i][stones.size() - 1] ? result : dp[i][stones.size() - 1]);
        return result;
    }
};

struct MaxSum{
public:
    int get_max_score(vector<int> const &stones){
        vector<int> sum(stones.size(), 0);
        vector<vector<int> > dp(stones.size(), sum);
        sum[0] = stones[0];
        for (int i = 1; i < stones.size(); ++ i)sum[i] = sum[i - 1] + stones[i];
        for (int j = 1; j < stones.size(); ++ j){
            for (int i = 0; i < stones.size(); ++ i){
                dp[i][j] = 0;
                for (int k = 0; k <j; ++ k){
                    int cur_temp = dp[i][k] + dp[(i + k + 1) % stones.size()][j - k - 1];
                    dp[i][j] = (dp[i][j] < cur_temp ? cur_temp : dp[i][j]);
                }
                int tail_index = (i + j) % stones.size();
                int cur_sum_temp = 0;
                if (tail_index > i)cur_sum_temp = sum[tail_index] - (i == 0 ? 0 : sum[i - 1]);
                else cur_sum_temp = sum[sum.size() - 1] - (i == 0 ? 0 : sum[i - 1]) + sum[tail_index];
                dp[i][j] += cur_sum_temp;
            }
        }
        int result = dp[0][stones.size() - 1];
        for (int i = 1; i < stones.size(); ++ i)result = (result > dp[i][stones.size() - 1] ? result : dp[i][stones.size() - 1]);
        return result;
    }
};

class Solution{
private:
public:
    void solve(){
        //ifstream infile("187in.txt");
        //cin.rdbuf(infile.rdbuf());
        int num_stone;
        while (cin >> num_stone){
            vector<int> stones(num_stone, 0);
            for (int i = 0; i < num_stone; ++ i)cin >> stones[i];
            MinSum min_s;
            MaxSum max_s;

            cout << min_s.get_min_score(stones) << ' ' << max_s.get_max_score(stones) << endl;
        }
    }
};


int main(){
    Solution so;
    so.solve();
    return 0;
}

ahdoc大神说有n^2算法,要给予一个不等式,另外ACRush还有一个nlogn的高端算法,基于斐波那契堆的贪心算法,这个就不去深究了。

Posted by richard爱闹 - 10月 6 2014
如需转载,请注明: 本文来自 Richard

combination

CS BS架构的区别

CS架构客户端是本地运行的一个程序,服务器端有数据库服务器端,还有衣蛾socket服务器端,通过socket与客户端进行通信
BS架构是请求响应模式,因此需要刷新页面,ajax风行后一定程度缓解。

BS架构优点:
1.客户端无需安装
2.BS架构放在互联网,交互性强
3.无须升级客户端,只需升级服务器

缺点:
1.跨浏览器方面不好
2.速度和安全性需要花费巨大设计成本
3.请求响应模式,需要刷新页面

最近get了递归转非递归之后,有点上瘾,几乎所有看到就想转非递归了。

找到规律其实就不难了,记录递归函数参数,然后还有一个type变量表示处于哪个位置

#include <iostream>
#include <vector>
#include <stack>
#include <cstring>
using namespace std;

class Solution {

public:
    struct info
    {
        int selectk ,k, selectn, n;
        int type;
    };
    bool select[10000];
    vector<vector<int> > ans;
    vector<int> curvec;
    vector<vector<int> > combine_select(int n, int k) {
        ans.clear();
        memset(select,0,sizeof(select));
        dfs(0,k,0,n);
        return ans;
    }
    void dfs(int selectk, int k, int selectn, int n)
    {
        if(selectn==n)
        {
            if(selectk==k)
            {
                vector<int> oneans;
                for(int i=0;i<n;i++)
                    if(select[i])
                        oneans.push_back(i+1);
                ans.push_back(oneans);
            }
        }
        else
        {
            select[selectn]=0;
            dfs(selectk,k,selectn+1,n);
            select[selectn]=1;
            dfs(selectk+1,k,selectn+1,n);
        }
    }
    vector<vector<int> > combine_vector(int n, int k) {
        ans.clear();
        curvec.clear();
        //memset(select,0,sizeof(select));
        dfs_vector(0,k,0,n);
        return ans;
    }

    vector<vector<int> > combination_iterative(int n, int k)
    {
        ans.clear();
        curvec.clear();
        stack<info> S;
        S.push({0,k,0,n,0});
        while(!S.empty())
        {
            info& cur=S.top();
            if(cur.selectk>cur.k)
            {
                S.pop();
            }
            else if(cur.selectn==cur.n)
            {
                if(cur.selectk==cur.k)
                    ans.push_back(curvec);
                S.pop();
            }
            else
            {
                if(cur.type==0)
                    cur.type++,S.push({cur.selectk,cur.k,cur.selectn+1,cur.n,0});
                else if(cur.type==1)
                    cur.type++,curvec.push_back(cur.selectn+1),S.push({cur.selectk+1,cur.k,cur.selectn+1,cur.n,0});
                else
                    curvec.pop_back(),S.pop();
            }
        }
        return ans;
    }


    void dfs_vector(int selectk, int k, int selectn, int n)
    {
        if(selectk>k) return;
        if(selectn==n)
        {
            if(selectk==k)
            {
                ans.push_back(curvec);
                /*
                vector<int> oneans;
                for(int i=0;i<n;i++)
                    if(select[i])
                        oneans.push_back(i+1);
                ans.push_back(oneans);*/
            }
        }
        else
        {
            //select[selectn]=0;
            dfs_vector(selectk,k,selectn+1,n);
            curvec.push_back(selectn+1);
            //select[selectn]=1;
            dfs_vector(selectk+1,k,selectn+1,n);
            curvec.pop_back();
        }
    }


} F;

int main()
{
    int n=4,k=2;
    vector<vector<int> > ans=F.combination_iterative(n,k);
    for(int i=0;i<F.ans.size();i++)
    {
        for(int j=0;j<F.ans[i].size();j++)
            cout<<F.ans[i][j]<<" ";
        cout<<endl;
    }
    return 0;
}

Posted by richard爱闹 - 10月 1 2014
如需转载,请注明: 本文来自 Richard

scanf printf

今天替战神助教,发现C语言scanf 一个问题还没掌握好。

int x, char c;//warning
long int k;
scanf(“i=%d c=%c”,&x,&c);
scanf(“k=&ld”,&k);

“%d”=” %d”=” \t %d”
也即%前面的若干个whitespace都是可以丢弃的

但是”i=%d”!=” i=%d”
所以前面的字符需要精确匹配,然后%紧接着前面的可以忽视掉一些whitespace,

“i=%d”=”i= %d”

并且scanf是以\n作为抽取输入流的结束符的例如

scanf(“%d\n”,&x)
先输入2 然后输入\n 匹配,最后再\n来表示输入流的结束

助教答疑的过程可以使自己查漏补缺,同时下次自己班的助教直接把问题写在黑板上,然后就可以避免那么多人问了。: )

Posted by richard爱闹 - 9月 30 2014
如需转载,请注明: 本文来自 Richard

Recursive to Nonrecursive

看了下小炒肉大神的代码,然后好像理解怎么讲递归代码转非递归了,函数体被N次递归划分成3块,然后用3个状态变量来区分当前层是在哪一个状态,top返回reference恰好可以完成这个任务,也即压站之后,还可以修改top的type的属性,然后每一块要处理相应的参数,然后压站,其实也就是自己写了一下系统的函数调用栈的代码

下了一下Qsort的非递归,以及DrawLine的代码

#include <iostream>
#include <stack>
using namespace std;

struct Info
{
    int low, high;
    int type;
    //Info generate();
};
/*
Info Info::generate()
{
    int mid=partition(a, low, high);
    if(type==0)
    {
        type++;
        return {low, mid-1, 0};
    }
    else
    {
        type++;
        return {mid+1,high,0};
    }
} */

int partition(int *a, int low, int high)
{
    int pivot=a[low],i=low;
    for(int j=low+1;j<=high;j++)
    {
        if(a[j]<pivot)//[low,i]:<pivot, [i+1,j-1]: >=pivot
        {
            swap(a[++i],a[j]);
        }
    }
    swap(a[i],a[low]);
    return i;
}

void Qsort(int *a, int low, int high)
{
    if(low<high)
    {
        int mid=partition(a, low, high);
        Qsort(a,low, mid-1);
        Qsort(a,mid+1, high);
    }
    else
        ;
}

void Qsort_nonrecursive(int *a, int low, int  high)
{
    stack<Info> S;
    S.push({low, high, 0});
    while(!S.empty())
    {
        Info &cur=S.top();
        if(cur.low<cur.high)
        {
            int mid=partition(a,cur.low, cur.high);
            if(cur.type==0)
                cur.type++,S.push({cur.low,mid-1,0});
            else if(cur.type==1)
                cur.type++,S.push({mid+1,cur.high,0});
            else
                S.pop();
        }
        else
        {
            S.pop();
        }
    }
}

/*
void Qsort_nonrecursive1(int* a, int low, int high)
{
    stack<Info> S;
    S.push({low, high});
    while(!S.empty())
    {
        Info &cur=S.top();
        if(cur.low<cur.high)
        {
            S.push(cur.generate());
        }
        else
        {
            S.pop();
            while(!S.empty())
                S.pop();
        }
    }
}
*/
void Show(int *a ,int n)
{
    for(int i=0;i<n;i++)
        cout<<a[i]<<" ";
    cout<<"\n";
}

int main()
{
    int a[]={2,3,4,523,4,5,345,4,4,24,4,4,1,1,1,1,325,246,537,346};
    int n=sizeof(a)/sizeof(int);
    Qsort_nonrecursive(a, 0,n-1);
    Show(a, n);
    return 0;
}

另外今天对于递归算法的时间复杂度计算,阮师兄大神建议背下主定理,因为之前总是怕过一段时间忘了,还是习惯自己plugin的方法带入计算,这个我后来看了下也不是很容易忘记,可以提高效率。算导的可读性绝对完爆国内那些填鸭式不易记忆的教材

T(n)=aT(n/b)+f(n)
如果f(n)多项式上大于n^(logb a), 或者小于, 取两者较大的。例如f(n)=O(n^(logb a-epsilon)),epsilon>0, 那么T(n)=O(logb a);
如果多项式上相等的话,则是T(n)=f(n)*lg n;

Posted by richard爱闹 - 9月 29 2014
如需转载,请注明: 本文来自 Richard

MaxPathSum

最早和瞿神合作写了一个比较复杂的版本的,现在打算 重新写,虽然 都是树形DP。

因此,每次调用左右子树的时候,要特别注意是否有一个是树杈行,有O(n)的算法,每次做两件事情,分别是更新基于当前root的path的最大值,四种选最大。

max{f(x.l)+f(x.r)+w(x),f(x.l)+w(x),f(x.r)+w(x),w(x)};

每个节点是递归找两个子树的最大,但是除去两个子树都需要的情况,三种选较大的,不然递归返回回去不能作为 父亲的子问题

最大PathSum

class Solution {
public:
    int maxPath;
    int maxPathSum(TreeNode *root)
    {
        if(!root) return 0;
        maxPath=root->val;
        maxPathNode(root);
        return maxPath;
    }

    int maxPathNode(TreeNode *root)
    {
        if(root==NULL) return 0;
        int leftmax=maxPathNode(root->left), rightmax=maxPathNode(root->right);

        maxPath=max(root->val, max(maxPath,max(leftmax+root->val+rightmax, max(leftmax+root->val, rightmax+root->val))));
        //cout<<maxPath<<endl;
        return max(root->val, max(leftmax+root->val, rightmax+root->val));
    }
};

今天突然发现stack.top() 是返回引用类型,这样的好处是可以S.top()=a; 函数返回值可以作为左值进行赋值操作,后者说cout<<a类似这种可以连续操作

Posted by richard爱闹 - 9月 28 2014
如需转载,请注明: 本文来自 Richard

expectation

ahdoc: 这道题目是水题,不值一提。

我等若菜:这道题目是一道概率题算期望,然后我是传统做法枚举每个事件的概率枚举求和,然后再加权求和,结果从小的数据上发现不了
规律,求教ahdoc 大神是设置Xi变量解方程来解的。

x3=0

x2=1/9+4/9x1+4/9x3

x1=1/3x2+1/3x0+1/3x1

x0=x1+1

Xi表示从i级到终极的期望消耗宝石个数,然后X0就是从0级到3级的期望的宝石个数

最后算出 X0=30

Posted by richard爱闹 - 9月 26 2014
如需转载,请注明: 本文来自 Richard

combination for all number

一道题目,抽象成数学就是6x+9y+140z=N, 找出最小的N使得任何M>=N, 都存在整数的x y z使得等式成立

这里面有一些结论性的东西,需要知道,否则不好弄。

2x+3y可以包括所有的>=2的整数(偶数由2表示,奇数由前一个偶数表示的一个2替换成3),然后6x+9y可以表示的任何>=6的3的倍数(6x+9y=3(2x+3y))

因此模3余1 和余2的由140来解决,140模3余2,140X2=280 模3余1,因此140-280之间的余1的数不能解决,因此至少需要280,但是3的倍数要>=6,因此280+6=286,但是前面还有几个模
3的整数,例如285, 284本身余2,可以由140去掉余2,然后3的倍数,283就不行了,因为余1的至少280,,3的倍数至少6,因此最终答案是284.

2013美团的笔试题,似乎搜狗的题也会有类似的题目。

见作者的分析。

http://blog.csdn.net/plumlzm/article/details/12590037

Posted by richard爱闹 - 9月 24 2014
如需转载,请注明: 本文来自 Richard

9 times to 1 numbers

瞿神的代码风格,典型的递归出口累加满足条件的个数。

对一个正整数作如下操作:如果是偶数则除以2,如果是奇数则加1,如此进行直到1时操作停止,求经过9次操作变为1的数有多少个?

这道题目似曾相识,但是 好像文法不同了。这道题目也应该是逆向思考,奇数只可能变偶数,偶数可能变奇数偶数,因此dfs搜索,到了cnt就累加
用map是为了避免重复搜索同一个数

编码方式的好博客
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstdlib>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define pb push_back
#define CLR(a,x) memset(a,x,sizeof(a))
map<int,int>q;
LL ans;
void dfs(int cur,LL tmp)
{
    if(cur==9/*||q[tmp]*/) {ans++;return;}
    //q[tmp]=1;
    if(tmp&1){
            if(tmp*2!=1)
                dfs(cur+1,tmp*2);

    }else {
        if(tmp*2!=1)
            dfs(cur+1,tmp*2);
        if(tmp-1!=1)
            dfs(cur+1,tmp-1);
        //ans+=2;
    }
    //return ans;
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    ans=0;
    q.clear();
    dfs(0,1);
    cout<<ans<<endl;
    return 0;
}

Posted by richard爱闹 - 9月 20 2014
如需转载,请注明: 本文来自 Richard

kangtuo

今天写了一道kth permutation 如果递归进去记录第k个时间复杂度是O(n!), 然后之前TLE其实本质是WA

现在写了一个基于选择的permutation,昨天去网易游戏宣讲会小炒肉写给我看,我很吃惊,因为一直写的是基于swap的,
然后和战神讨论,发现啊哈算法也是这种的,其实机遇swap的 字典序输出也有思路,但是代码一直调不出不知是不是风水不好。

然后想起来逆康拓展开,瞿神提到过,但是没细看,后来和ahdoc大神吃饭,大神说到了具体的细节,于是看到伟哥写了一个非递归的算法,有点难写。

我决定第一次写逆康拓展开发现还挺好写的,时间复杂度O(n^2), 需要注意的是:

  1. k— 因为除和取余都是0-based,
  2. 同时算出来的商也是0-based, 因此cnt++ 与curnum+1比
  3. 然后记住循环是n-1轮,最后遍历一遍把最后一个元素加进去。

1.2 的两次— ++ 不能合并消掉,因为例如n=3, k=6 第一次就算出3,后面0就没法弄了。因为涉及到去摸都是0-based,k—是必须的,同时商也是0based, 因此cnt++ 与curnum+1(curnum=k/(n-i)!)

class Solution
{
public:
    bool used[100000];
    int f(int n)
    {
        int product=1;
        for(int i=n;i>=1;i--) product*=i;
        return product;
    }
    string getPermutation(int n, int k)
    {
        string kthper;
        int cnt;
        memset(used,0,sizeof(bool)*n);
        int jie=f(n-1);
        k--;
        for(int i=1;i<n;i++)
        {
            int curnum=k/jie;
            k=k%jie;
            jie/=(n-i);
            cnt=0;
            for(int i=0;i<n;i++)
            {
                if(!used[i])
                {
                    cnt++;
                    if(cnt==(curnum+1))
                    {
                        kthper+=char(i+1+'0');
                        used[i]=1;
                    }
                }
            }
        }
        for(int i=0;i<n;i++)
            if(!used[i])
                kthper+=char(i+1+'0');
        return kthper;
    }
};

今天做到一道向量点积最大的题目,有种似曾相识的感觉,但是就是不记得怎么做了。

然后暴搜先用vector存了全排列结果MLE,然后换数组,每次遍历就计算点积,结果TLE,因为n=1000时,是1000的阶乘非常大了,算法肯定不行。

后来小炒肉大神说感觉像是a 增旭排,b降序排,然后对应向量点积,这就是最小,但是不好证明。

后来吃饭的时候,小炒肉大神想到了方法证明,a1b2>…bn 那么当交换a,例如交换a1,ak, 那么乘以b1带来的增加比乘以bk带来的降低要多,导致点积点积增加。
b1(ak-a1)>bk(ak-a1), 每次交换都是增加,后面的排列都比这个的点积大,因此这个点积是最小的。

今天看到C++为啥不是++C,因为后增运算还可以使用原始值,也即C,而C++是C继承过来的,是他的超集,如果++C就不能再沿用C了与实际不符,挺有趣的
http://www.cnblogs.com/maxwellp/archive/2012/02/11/2346844.html

Posted by richard爱闹 - 9月 12 2014
如需转载,请注明: 本文来自 Richard

Merge In Place

昨天和战神研究出了一个新的就地merge两个数组的算法,可能是已有的。

空间复杂度是O(1), 时间复杂度最坏可能会达到O(n^2)

算法保证每次循环结束之后a[i…k] 和a[j…n-1] 分别是有序的,这样其实是包含了原问题的子问题,还可以尝试递归。

之前保证a[i] a[j]中存在未处理数组里最小的数 可能会有问题,因此后面还是需要有个while将比交换过来的数更小的数都遍历到底

void f(int *a, int k, int n)
{
    int i=0, j=k+1;
    while(i<=k && j<=n-1)
    {
        if(a[i]>a[j])
        {
            swap(a[i],a[j]);
            int l=j+1,tmp=a[j];
            while(l<=n-1 && tmp>a[l])
                a[l-1]=a[l],l++;
            a[l-1]=tmp;
            i++;
        }
        else
        {
            i++;
        }
    }
}

Posted by richard爱闹 - 9月 12 2014
如需转载,请注明: 本文来自 Richard