• 序列相关的趣题 之三


    (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;
    }



  • 相关阅读:
    xcode 常用插件 加快开发速度 --严焕培
    iOS,蓝牙开发!!--By帮雷
    获取加速度数据,陀螺仪数据,磁场数据的两种方式-陈鹏
    简单仿京东"筛选"界面 双导航栏控制器共存 by Nicky.Tsui
    扩展NSDate类实现快捷使用 —— 昉
    如何实现视图圆角效果的三种方法及比较——董鑫
    无意进去UIView随笔闹腾着玩 -by 胡 xu
    简单实现UITableView索引功能(中英文首字母索引)(一) ByH罗
    动画推荐-By胡罗
    [手游项目3]-20-golang向上取整、向下取整和四舍五入
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4230110.html
Copyright © 2020-2023  润新知