1:汉诺塔问题
面试题 08.06. 汉诺塔问题 - 力扣(LeetCode) (leetcode-cn.com)https://leetcode-cn.com/problems/hanota-lcci/
class Solution {
public:
void zhuanYi(int i,vector<int>&from,vector<int>&other,vector<int>&to){
if(i==1){int ding=from.back();from.pop_back();to.push_back(ding);}
else{
zhuanYi(i-1,from,to,other);//from搬到other
int ding=from.back();
from.pop_back();
to.push_back(ding);
cout<<"i-1是"<<i-1<<endl;
cout<<other.size()<<endl;
zhuanYi(i-1,other,from,to);
}
}
void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {
zhuanYi(A.size(),A,B,C);
}
};
2:全排列(使用“分支限界”提前杀死重复的路,实现不重复)(不开辟新的数组,直接在原数组位置上改变)
class Solution {
public:
void xunhuan(vector<int>&nums,int i,vector<vector<int>>&result){
if(i==nums.size()){
result.push_back(nums);return;
}
unordered_set<int>xi;
for(int j=i;j<nums.size();j++){
if(xi.count(nums[j])!=0){continue;}
xi.insert(nums[j]);
//哈希的三个函数:插入inseret,擦除erase,计数count,
//寻找find:判断有无map.find(key) == map.end(),
swap(nums[i],nums[j]);
xunhuan(nums,i+1,result);
swap(nums[i],nums[j]);
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>>result;
xunhuan(nums,0,result);
return result;
}
};
元素的全排列以最简单的三元素为例可以大概描述成,先固定前几位,再交换后两位。
多元素的全排列思路也大概如此,
将第i位后面的各个元素分别和当前的i元素进行交换,也就是i及其以后的各个元素都可以轮流做i的这个位置。对i的位置的各个子情况同样的方法进行下一元素的任命处理。直到处理到尾部了便是处理好了一种结果,逐步递归。
同时为了不产生重复结果(所谓的重复结果主要是因为数组中有相同元素,这样会造成相同元素都做过了一个位子)
在对第i个位子进行子情况遍历时,设立哈希set存储第i个位置谁已经做过了,防止重复。
相比于将所有结果得到去掉重复的方法来说,指标上没有优化(最差情况下没有优化),但是常数项上有优化。
另:哈希的三个函数:插入inseret,擦除erase,计数count,
寻找find:判断有无map.find(key) == map.end(),
3:给定一个整型数组arr,代表数值不同的纸牌排成一条线。玩家A和玩家B依次拿走每张纸牌,规定玩家A先拿,玩家B后拿。但是每个玩家每次只能拿走最左或最右的纸牌,玩家A和玩家B都绝顶聪明。请返回最后获胜者的分数。
#include <bits/stdc++.h>
using namespace std;
int s(vector<int>arr, int i, int j);//子函数相互调用时,可以先证明再写具体的
int f(vector<int>arr, int i, int j) { //返回先手
if (i == j) {
return arr[i];
}
return max( arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1));
}
int s(vector<int>arr, int i, int j) {
if (i == j) {
return 0;
}
return min( f(arr, i + 1, j), f(arr, i, j - 1) );
}
int win(vector<int>arr) {
if (arr.size() == 0) {
return 0;
}
return max( f(arr, 0, arr.size() - 1), s(arr, 0, arr.size() - 1 ));
}
int main() {
vector<int>arr;
int pp;
while (cin >> pp) {
arr.push_back(pp);
}
//输入结束时输进去一个字符(因为字符不符合向量的属性)来结束输入,或者按ctrl+z结束输入
//或者加入终止标识符
return win(arr);
}
4:栈的逆序(不使用新的数据结构)
#include <iostream>
#include <stack>
using namespace std;
int f(stack<int> &p) { //返回为底部元素,并且向下压
int ding = p.top();
p.pop();
if (p.empty()) {
return ding;
} else {
int last = f(p);
p.push(ding);
return last;
}
}
void reverse(stack<int> &p) {
if (p.empty()) {
return;
}
int i = f(p); //获得底并且向下压
reverse(p);
p.push(i);
}
int main() {
stack<int>p;
for (int i = 0; i < 10; i++) {
p.push(i + 1);
}
//
// cout << "输出按照从栈顶向栈底" << endl;
// stack<int>q;
// q = p;
//
// while (!q.empty()) {
// cout << q.top() << endl;
// q.pop();
// }
reverse(p);
// cout << "输出按照从栈顶向栈底" << endl;
//
// while (!p.empty()) {
// cout << p.top() << endl;
// p.pop();
// }
return 0;
}
5:规定1和A对应、2和B对应、3和C对应…26和Z对应,那么一个数字字符串比如"111”就可以转化为:“AAA”、“KA"和"AK”。给定一个只有数字字符组成的字符串str,请问有多少种转化结果?
6:给定两个长度都为N的数组weights和values,weights[i]和values[i]分别代表 i号物品的重量和价值。给定一个正数bag,表示一个载重bag的袋子,你装的物品不能超过这个重量。返回你能装下最多的价值是多少?