zoukankan      html  css  js  c++  java
  • 序列相关的趣题 之三

    (6) 给定1-n的一个排列,每次操作定义为把一个数放到序列的末尾,请问把它排好顺序,至少要操作多少次?

    这个题好像是tc某个题的变种,也是google的面试题。tc原来的问题略微复杂一点,比方是给定一个序列,至少多少次操作转换成另外一个序列。可是又一次编号之后等价于如上问题——google面试题好像就是上面那个描写叙述,也可能是放到序列开头,可是方法是一样的。

    首先,至多n次操作是能够做到的,我们按顺序把1,2,3,4……n放到末尾就能够了。

    其次,我们为什么要移动1? 假设其它数都移动好了,1不动不就完了么?

    再次,假设我们某部操作把x放到了末尾,那么以后的操作肯定是把(x + 1)放到末尾,把(x + 2)放到末尾……把n放到末尾,所以要动x,比x大的那些所有都要动,一个都不能少。

    于是,我们实质是求尽可能大的一个x,把x..n都移动了。那么没移动的那些数,必须是按顺序的,也就是1..x - 1必须是按顺序出如今原始序列里的,仅仅有这样,我们动了>=x的才干形成一个排好顺序的序列。

    问题简单了O(n)解决……

    int solution(vector<int> &a) {
    int n = a.size(), want = 1;
    	for (int i = 0; i < n; ++i) {
    		if (a[i] == want) {
    			++want;
    		}
    	}	
    	// want .. n must be moved
    	return n - want + 1;
    }
    

    (7) 给定1-n的一个排列,每次操作定义为把一个数放到序列的末尾或开头,请问把它排好顺序,至少要操作多少次?

    我印象中这个题是摩根比赛的一个题的变种。与(6)很相近,可是操作种类很多其它了。延续上一个题的思路,我们终于肯定是把1..y移动倒开头(倒序),把x..n 移动倒末尾(顺序)中间的不动。问题就是中间那部分怎样尽可能长? 採用dp的思路。

    dp[x]表示从往后能够“连接的长度”,即x,x + 1, ...x + dp[x] - 1按顺序出现。 那假设我们倒着循环i,有 dp[a[i]] = dp[a[i] + 1] + 1 ,然后终于结果是n - max(dp[x]), (注意右边没出现的设置为0,+1后自己主动变为1,符合我们的定义) 


    int solution(vector<int> &a) {
    int n = a.size(), m = 0;
    vector<int> dp(n + 2, 0);  //使用1..n + 1 注意下标范围
    	for (int i = n - 1; i >= 0; --i) {
    		m = max(m, dp[a[i]] = dp[a[i] + 1] + 1);
    		
    	}
    	return n - m;
    }



  • 相关阅读:
    用户场景描述
    个人工作总结(第一阶段)
    个人进度报告
    《构建之法》阅读笔记05
    《构建之法》阅读笔记04
    《构建之法》阅读笔记03
    2020寒假学习(14)
    2020寒假学习(13)
    2020寒假学习(12)
    2020寒假学习(11)
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4230110.html
Copyright © 2011-2022 走看看