1、交换完全二叉树某子树
第一眼看上去需要建立二叉树,但是因为是完全二叉树,可以直接用数组代替,对于每个节点n,其子树为2n和2n+1,因此直接根据这个规律操作数组即可。
因为对于节点n,其子树也需要交换,因此这里采用递归,对节点n的子树及其子树节点也进行交换。
对于节点n,首先判断其左右子树是否存在,如果不存在,直接返回;如果存在,则对左右子树进行递归,最后左右子树全部交换完后,再对当前节点的左右子树进行交换。
因为对于节点n,其子树也需要交换,因此这里采用递归,对节点n的子树及其子树节点也进行交换。
对于节点n,首先判断其左右子树是否存在,如果不存在,直接返回;如果存在,则对左右子树进行递归,最后左右子树全部交换完后,再对当前节点的左右子树进行交换。
#include<iostream>
#include<vector>
using namespace std;
void dfs(vector<int> &arr, int left, int right)
{
if (left > arr.size() - 1 || right > arr.size() - 1)
return;
else
{
dfs(arr, 2 * left+1, 2 * right+1);
dfs(arr, 2 * (left + 1), 2 * (right + 1));
swap(arr[left], arr[right]);
return;
}
}
int main()
{
vector<int> arr = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
int n = 3;
dfs(arr, 2 * n-1, 2 * n);
for (int i = 0; i < arr.size(); i++)
cout << arr[i] << " ";
cout << endl;
system("pause");
return 0;
}
2、有N种商品,每种商品有N_i个,现在需要将K个不同的商品放入福袋中,问最多可以做多少个福袋
我的思路是,尽可能先拿个数多的那种商品。
首先将个数最多的K个商品,每种中拿出1个,然后对剩余的个数进行排序,再从个数最多的K个中每种拿出一个...每次拿之前先判断剩余商品种类是否大于K个。
首先将个数最多的K个商品,每种中拿出1个,然后对剩余的个数进行排序,再从个数最多的K个中每种拿出一个...每次拿之前先判断剩余商品种类是否大于K个。
int main()
{
int N, K;
cin >> N >> K;
vectorarr(N, 0);
for(int i = 0; i< N; i++)
cin >> arr[i];
int flag = 0;
int res = 0;
while(1)
{
flag = 0;
for(int i = 0; i< N; i++)
if(arr[i] > 0)
flag++;
if(flag < K)
break;
sort(arr.begin(), arr.end());
for(int i = arr.size()-1; i >= arr.size()-K; i--)
arr[i]--;
res++;
}
cout << res << endl;
return 0 ;
}
3、老王打字:①输入一个字母,步数加1;选定全部已输入字符,步数加2;复制全部选定字符,步数加2;粘贴全部复制字符,步数加2;按ESC取消选择,步数加1;
问:输入N个字最少需要多少步。
动态规划:
假设F(n)表示输入n个字需要的步数。
F(0) = 0;
F(1) = 1;
F(2) :分情况讨论:①在输入了1个字的基础上,再输入1个字,即F(2) = F(2-1) + 1;②第二、三种情况,这里不明显,后面讨论
F(3) :分情况讨论:①在输入1个的基础上输入2个,在输入2个的基础上输入1个,即F(3) = min( F(3-2) + 2, F(3 - 1) + 1),两种情况中取最小值;②第二、三种情况,这里还是不明显,下一步讨论
........
F(10) :分情况讨论:
①即为上面,在输入了i个字符的基础上,再输入10-i个,(i为从1到9);
②第二种情况:输入了i个字符后,我复制这i个字符,取消选择,然后在后面进行多次粘贴,这里的i可以从1到10/2;循环取i,求最小值,需要注意的是,当10%i不为0时,需要再加上F(10%i);
③第三种情况:输入了i个字符后,我还是复制粘贴这i个字符,但是上面②是复制之后,取消选择,在原来的后面继续粘贴;这里我复制之后,输入一个字符,将原来输入的都覆盖掉,然后再粘贴;
假设F(n)表示输入n个字需要的步数。
F(0) = 0;
F(1) = 1;
F(2) :分情况讨论:①在输入了1个字的基础上,再输入1个字,即F(2) = F(2-1) + 1;②第二、三种情况,这里不明显,后面讨论
F(3) :分情况讨论:①在输入1个的基础上输入2个,在输入2个的基础上输入1个,即F(3) = min( F(3-2) + 2, F(3 - 1) + 1),两种情况中取最小值;②第二、三种情况,这里还是不明显,下一步讨论
........
F(10) :分情况讨论:
①即为上面,在输入了i个字符的基础上,再输入10-i个,(i为从1到9);
②第二种情况:输入了i个字符后,我复制这i个字符,取消选择,然后在后面进行多次粘贴,这里的i可以从1到10/2;循环取i,求最小值,需要注意的是,当10%i不为0时,需要再加上F(10%i);
③第三种情况:输入了i个字符后,我还是复制粘贴这i个字符,但是上面②是复制之后,取消选择,在原来的后面继续粘贴;这里我复制之后,输入一个字符,将原来输入的都覆盖掉,然后再粘贴;
int main()
{
int N;
cin >> N;
vectordp(N+1, 99999);
dp[0] = 0;
dp[1] = 1;
for(int i = 2; i <= N; i++)
{
for(int j = 1; j <= i; j++)
dp[i] = min(dp[i], dp[i-j] + j); //情况①
for(int j = 1; j <= i/2; j++)
{
dp[i] = min(dp[i], dp[j] + i/j*2 + 3 + dp[i%j]); //情况②
dp[i] = min(dp[i], dp[j] + i/j*2 + 5); //情况③
}
}
cout << dp[N] << endl;
return 0;
}

京公网安备 11010502036488号