第一题吃货馋嘴分披萨
,考察深度优先遍历和动态规划处理环形数组问题,在一个环形数组(比萨)中,每次可以选择左边或右边的元素,并且每次选择的元素必须是当前可选元素中的最大值,求能够选择的元素的最大和。
第二题字符串变换最小字符串
,考察对字符串的处理,从后面向前面查找,把倒数第一个字典序最小字符的与第一个字符替换,保证最小。
第三题满足要求的最长子串
,考察滑动窗口+字符串的处理,使用滑动窗口来找出只包含一个字母和任意数量数字的最长子串。
第一题 吃货馋嘴分披萨(100) “吃货”和”馋嘴”两人到披萨店点了一份铁盘圆形披萨,并嘱咐店员将披萨按放射状切成大小相同的偶数个小块。但是粗心的服务员将披萨切成了每块大小都完全不同奇数块,且肉眼能分辨出大小。
由于两人都想吃到最多的披萨,他们商量了一个他们认为公平的分法:从”吃货”开始,轮流取被萨。除了第一块破产可以任意选取外,其他都必须从缺口开始选。
他俩选披萨的思路不同。”馋嘴”每次都会选最大块的披萨,而且”吃货”知道”馋嘴”的想法。
已知披萨小块的数量以及每块的大小,求”吃货”能分得的最大的披萨大小的总和。
输入描述:
1.第1行为一个正整数奇数 N,表示披萨小块数量。 2.接下来的第 2 行到第 N + 1行(共 N 行),每行为一个正整数,表示第 i 块披萨的大小。
说明: 3 <= N <= 500 1 <= i <= N 每块披萨的大小范围为[1, 2147483647]
输出描述:
“吃货”能分到的最大的披萨大小的总和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 #include <bits/stdc++.h> using namespace std;vector<vector<long >> memory; long backtrace (vector<long > nums, int n, int left, int right) { if (nums[left] > nums[right]) { left = left < 0 ? left : (left + n + 1 ) % n; } else if (nums[left] < nums[right]) { right = right < 0 ? right : (right + n - 1 ) % n; } if (memory[left][right] <= 0 ) { if (left == right) { memory[left][right] = nums[left]; } else { int newLeft = (left + 1 ) % n; int newRight = (right + n - 1 ) % n; memory[left][right] = nums[left] + backtrace (nums, n, newLeft, right); if (nums[right] + backtrace (nums, n, left, newRight) > memory[left][right]) { memory[left][right] = nums[right] + backtrace (nums, n, left, newRight); } } return memory[left][right]; } else { return memory[left][right]; } } int main () { int n; while (cin >> n) { vector<long > nums (n) ; for (int i = 0 ; i < n; i++) { cin >> nums[i]; } for (int i = 0 ; i < n; i++) { vector<long > tmp; memory.push_back (tmp); for (int j = 0 ; j < n; j++) { memory[i].push_back (0 ); } } long res = 0 ; int i = 0 ; while (1 ) { if (i > n - 1 ) { break ; } else { int left = (i + n + 1 ) % n; int right = (i + n - 1 ) % n; long target = backtrace (nums, n, left, right); if (target + nums[i] > res) { res = target + nums[i]; } } i++; } cout << res << endl; } return 0 ; }
第二题 字符串变换最小字符串(100) 给定一个字符串s,最多只能进行一次变换,返回变换后能得到的最小字符串(按照字典序进行比较)。 变换规则:交换字符串中任意两个不同位置的字符。
输入描述:
一串小写字母组成的字符串s。
说明: s是都是小写字符组成 1 <= s.length <= 1000
输出描述:
按照要求进行变换得到的最小字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <bits/stdc++.h> using namespace std;int main () { string str; while (cin >> str) { char minChar = 'z' ; int minCharIndex = 0 ; for (int i = str.size () - 1 ; i >= 0 ; i--) { if (str[i] <= minChar) { minChar = str[i]; minCharIndex = i; } } char tmp = str[0 ]; str[0 ] = minChar; str[minCharIndex] = tmp; cout << str << endl; } return 0 ; }
第三道 满足要求的最长子串(200) 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度,字符串本身是其最长的子串,子串要求:
只包含1个字母(a ~ z, A ~ Z),其余必须是数字。
字母可以在子串中的任意位置。
如果找不到满足要求的子串,如全是字母或全是数字,则返回-1。
输入描述:
字符串(只包含字母和数字)
输出描述:
子串的长度,没有满足要求的子串,返回-1
解题思路:
什么时候右边界滑动:每次滑动一个 什么时候形成滑动窗口:当charCount = 1 && numCount >=1 什么时候左边界滑动:当charCount > 1时,当charCount == 1时停止
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 #include <bits/stdc++.h> using namespace std;int maxLength (string str) { int left = 0 , right = 0 ; int charCount = 0 , digitCount = 0 , maxCount = -1 ; while (right < str.size ()) { if (isdigit (str[right])) { digitCount++; } else { charCount++; } if (charCount == 1 && digitCount > 0 ) { maxCount = max (maxCount, right + 1 - left); } while (charCount > 1 ) { if (isdigit ((str[left]))) { digitCount--; } else { charCount--; } left++; } right++; } return maxCount; } int main () { string str; while (cin >> str) { cout << maxLength (str) << endl; } return 0 ; }