题目一:
正整数N从1开始,每次操作可以选择对N加1或者对N乘2.若想获得正整数M,最少需要多少个操作。
样例:
输入:5
输出:3
动态规划:
#include <iostream>
using namespace std;
int minOpt(int M)
{
if (M<=1 || M>=65536)
return -1;
if (M == 2)
return 1;
else
{
int num[M+1];
num[0] = -1;
num[1] = -1;
num[2] = 1;
for(int i=3;i<=M;i++)
{
if(i%2 == 0)
{
num[i] = (num[i-1] < num[i/2] ? (num[i-1]+1) : (num[i/2]+1));
}
else
num[i] = num[i-1]+1;
}
return num[M];
}
}
int main()
{
int M;
while(cin >> M)
{
int res = minOpt(M);
cout << res << endl;
}
return 0;
}
题目二:
矩阵输出,给定一个二维矩阵,请将其中的元素按Z字形打印出来。
样例:
输入:
4 5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
输出:1 2 6 11 7 3 4 8 12 16 17 13 9 5 10 14 18 19 15 20
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int m, n;
scanf("%d %d", &m, &n);
int input[m][n];
for (int i=0; i<m; i++) {
for (int j=0; j<n; j++) {
cin >> input[i][j];
}
}
int i=0;
int j=0;
do {
cout << input[i][j];
cout << " ";
if ((i+j)%2 == 0) //行列之和为偶数
{
if (i == 0 && j<(n-1))
{
j++;
}
else if (j == (n-1))
{
i++;
}
else
{
i--;
j++;
}
}
else { //行列之和为奇数
if (j == 0 && i<(m-1))
{
i++;
}
else if (i == (m-1))
{
j++;
}
else {
i++;
j--;
}
}
}
while (i<m && j<n);
i--;
j++;
do {
if (i<m && j<n) {
cout << input[i][j];
cout << " ";
} else {
break;
}
if ((i+j)%2 == 0) //行列之和为偶数
{
if (j == 0 && i<(n-1))
{
i++;
}
else if (j == (n-1))
{
i++;
}
else {
i--;
j++;
}
}
else { //行列之和为奇数
if (j == 0 && i<(m-1))
{
i++;
}
else if (i == (m-1))
{
j++;
}
else
{
i++;
j--;
}
}
}
while (i<m && j<n);
return 0;
}
题目三:
给定一个无序的数组nums,重排序使其满足这种顺序:nums[0] < nums[1] > nums[2] < nums[3]...
Note:
可以假设所有的输入都是有效输入。
Follow Up:
是否能够在O(n)的时间复杂度或者O(1)的空间复杂度下完成算法。(leetcode324题--Wiggle Sort II)。
//时间复杂度O(n),空间复杂度O(n)。
class Solution {
public:
void wiggleSort(vector<int>& nums) {
vector<int> tmp = nums;
int n = nums.size(), k = (n+1)/2, j = n;
sort(tmp.begin(), tmp.end());
for (int i=0; i<n; ++i) {
nums[i] = i&1 ? tmp[--j] : tmp[--k];
}
}
};
/**
1. 使用O(n)时间复杂度的quickSelect算法,从未经排序的数组nums中选出中位数mid
2. 参照解法I的思路,将nums数组的下标x通过函数idx()从[0, 1, 2, ... , n - 1, n] 映射到 [1, 3, 5, ... , 0, 2, 4, ...],得到新下标ix
3. 以中位数mid为界,将大于mid的元素排列在ix的较小部分,而将小于mid的元素排列在ix的较大部分。
详见:https://discuss.leetcode.com/topic/32929/o-n-o-1-after-median-virtual-indexing/2
*/
//时间复杂度O(n),空间复杂度O(1)。笔试题中出现过
class Solution {
public:
void wiggleSort(vector<int>& nums) {
int n = nums.size();
auto midptr = nums.begin() + n/2;
/**nth_element可以使第n大元素处于第n位置(从0开始,其位置是下标为 n的元素)
并且比这个元素小的元素都排在这个元素之前,比这个元素大的元素都排在这个元素之后,但不能保证他们是有序的
*/
nth_element(nums.begin(), midptr, nums.end()); //保证O(n)的平均时间复杂度
int mid = *midptr;
#define A(i) nums[(1+2*(i))%(n|1)] //保证先输出奇数再输出偶数
int i = 0, j = 0, k = n-1;
while (j <= k) {
if (A(j) > mid)
swap(A(i++), A(j++));
else if (A(j) < mid)
swap(A(j) , A(k--));
else
j++;
}
}
};