reverse-string
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int layer=triangle.size();
int result=100000;
vector<int> tmp_min(layer,0);
tmp_min[0]=triangle[0][0];
for(int i=1;i<layer;i++){
for(int j=i;j>=0;j--){
if(j==0){
tmp_min[0]=tmp_min[0]+triangle[i][0];
}else if(j==i){
tmp_min[i]=tmp_min[i-1]+triangle[i][i];
}else{
tmp_min[j]=min(tmp_min[j-1],tmp_min[j])+triangle[i][j];
}
}
}
for(int i=0;i<layer;i++){
if (tmp_min[i]<result){
result=tmp_min[i];
}
}
return result;
}
};
最长连续序列
给定一个未排序的整数数组,找出最长连续序列的长度。
要求算法的时间复杂度为 O(n)。
示例:
输入: [100, 4, 200, 1, 3, 2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。
思路:用set记录元素,然后对于每一个数不断在set中找它的连续序列;如果num-1存在于set中,则不从这个数开始查找。
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
set<int> setInt;
int result=0,tmp_result;
for(auto num:nums){
setInt.insert(num);
}
for(auto num:nums){
auto iter=setInt.find(num-1);
if(iter==setInt.end()){
num+=1;
tmp_result=1;
while(true){
iter=setInt.find(num);
if(iter!=setInt.end()){
tmp_result+=1;
}else{
break;
}
num+=1;
}
if(tmp_result>result){
result=tmp_result;
}
}
}
return result;
}
};
最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
class Solution {
public:
int rows,cols;
int minPathSum(vector<vector<int>>& grid) {
rows=grid.size();
cols=grid[0].size();
int cur_r=0,cur_c=0;
int pos_r,pos_c;
int a,b;
int max=100000000;
while(true){
if(cur_r+1<rows || cur_c+1<cols){
if(cur_c+1<cols){
pos_r=cur_r;
pos_c=cur_c+1;
cur_r=pos_r;
cur_c=pos_c;
// cout<<"cur"<<cur_r<<cur_c<<endl;
while(check(pos_r,pos_c)){
// cout<<"pos"<<pos_r<<pos_c<<endl;
a=(check(pos_r-1,pos_c)) ? grid[pos_r-1][pos_c] : max;
b=(check(pos_r,pos_c-1)) ? grid[pos_r][pos_c-1] : max;
grid[pos_r][pos_c]=(a<b) ? a+grid[pos_r][pos_c]:b+grid[pos_r][pos_c];
pos_r+=1;
pos_c-=1;
}
}else{
pos_r=cur_r+1;
pos_c=cur_c;
cur_r=pos_r;
cur_c=pos_c;
// cout<<cur_r<<cur_c<<endl;
while(check(pos_r,pos_c)){
a=(check(pos_r-1,pos_c)) ? grid[pos_r-1][pos_c] : max;
b=(check(pos_r,pos_c-1)) ? grid[pos_r][pos_c-1] : max;
grid[pos_r][pos_c]=(a<b) ? a+grid[pos_r][pos_c]:b+grid[pos_r][pos_c];
pos_r+=1;
pos_c-=1;
}
}
}else{
return grid[cur_r][cur_c];
}
}
return 0;
}
bool check(int r,int c){
if(r>=0 && r<rows && c>=0 && c<cols ){
return true;
}else{
return false;
}
}
};
不同路径 II
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2
class Solution {
public:
int rows,cols;
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
auto grid=obstacleGrid;
if(grid[0][0]==1){
return 0;
}
grid[0][0]=1;
rows=grid.size();
cols=grid[0].size();
int cur_r=0,cur_c=0;
int pos_r,pos_c;
int a,b;
while(true){
if(cur_r+1<rows || cur_c+1<cols){
if(cur_c+1<cols){
pos_r=cur_r;
pos_c=cur_c+1;
cur_r=pos_r;
cur_c=pos_c;
// cout<<"cur"<<cur_r<<cur_c<<endl;
while(check(pos_r,pos_c)){
if (grid[pos_r][pos_c]==1){
grid[pos_r][pos_c]=0;
}else{
a=(check(pos_r-1,pos_c) ) ? grid[pos_r-1][pos_c] : 0;
b=(check(pos_r,pos_c-1)) ? grid[pos_r][pos_c-1] : 0;
grid[pos_r][pos_c]=a+b;
}
pos_r+=1;
pos_c-=1;
}
}else{
pos_r=cur_r+1;
pos_c=cur_c;
cur_r=pos_r;
cur_c=pos_c;
// cout<<cur_r<<cur_c<<endl;
while(check(pos_r,pos_c)){
if (grid[pos_r][pos_c]==1){
grid[pos_r][pos_c]=0;
}else{
a=(check(pos_r-1,pos_c) ) ? grid[pos_r-1][pos_c] : 0;
b=(check(pos_r,pos_c-1)) ? grid[pos_r][pos_c-1] : 0;
grid[pos_r][pos_c]=a+b;
}
pos_r+=1;
pos_c-=1;
}
}
}else{
return grid[cur_r][cur_c];
}
}
return 0;
}
bool check(int r,int c){
if(r>=0 && r<rows && c>=0 && c<cols ){
return true;
}else{
return false;
}
}
};
跳跃游戏
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。
思路: 维护一个可到达的最大点
class Solution {
public:
bool canJump(vector<int>& nums) {
int len=nums.size();
int range=0;
int tmp;
for(int i=0;i<len;i++){
if(i<=range){
tmp=i+nums[i];
if(tmp>range){
range=tmp;
}
}else{
break;
}
}
if(range>=(len-1)){
return true;
}else{
return false;
}
}
};
45. 跳跃游戏 II
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
思路: 用优先队列记录当前距离最小的节点,如果最小的节点不能到达当前节点则pop
其实更简单的方法是直接贪婪的选择能跳的更远的下一个节点
struct Pair
{
int range;
int distance;
Pair(int a,int b){
distance=a;
range=b;
}
bool operator<(const Pair& a) const
{
return distance>a.distance;
}
};
class Solution {
public:
int jump(vector<int>& nums) {
int len=nums.size();
priority_queue<Pair> q;
Pair first(0,nums[0]);
q.push(first);
int result;
for(int i=1; i<len;i++){
while(!q.empty()){
auto top=q.top();
if(top.range>=i){
Pair cur(top.distance+1,nums[i]+i);
result=top.distance+1;
q.push(cur);
break;
}else{
q.pop();
}
}
}
return result;
}
};
最长回文子串
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
class Solution {
public:
string longestPalindrome(string s) {
int len=s.size();
if(len==1 || len==0){
return s;
}
int j;
int result=0;
int left;
int right;
vector<vector<bool>> dp(len,vector<bool>(len,false));
for (int l=1; l<=len;l++){
for(int i=0;i<len-l+1;i++){
j=i+l-1;
// cout<<i<<" "<<j<<endl;
if(l==2){
// cout<<"l"<<l<<endl;
if(s[i]==s[j]){
dp[i][j]=true;
if(l>result){
result=l;
left=i;
right=j;
}
}
}else if(l==1){
dp[i][j]=true;
if(s[i]==s[j]){
dp[i][j]=true;
if(l>=result){
result=l;
left=i;
right=j;
}
}
}else{
// cout<<i<<j<<endl;
// cout<<"s"<<s[i]<<s[j]<<endl;
// cout<<"dp"<<dp[i+1][j-1]<<endl;
if(s[i]==s[j] && dp[i+1][j-1]){
dp[i][j]=true;
if(l>result){
result=l;
left=i;
right=j;
}
}
}
}
}
return s.substr(left,result);
}
};
最长公共子序列
给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。
若这两个字符串没有公共子序列,则返回 0。
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int len1=text1.size();
int len2=text2.size();
vector<vector<int>> dp(len1+1,vector<int>(len2+1,0));
for(int i=1;i<len1+1;i++){
for(int j=1;j<len2+1;j++){
if(text1[i-1]==text2[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
}
}
}
return dp[len1][len2];
}
};
编辑距离
给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符
class Solution {
public:
int minDistance(string word1, string word2) {
int len1=word1.size();
int len2=word2.size();
int t;
vector<vector<int>> dp(len1+1,vector<int>(len2+1,0));
for(int i=0; i<len1+1;i++){
dp[i][0]=i;
}
for(int i=0; i<len2+1;i++){
dp[0][i]=i;
}
for(int i=1; i<len1+1;i++){
for(int j=1;j<len2+1;j++){
if(word1[i-1]==word2[j-1]){
dp[i][j]=dp[i-1][j-1];
}else{
dp[i][j]=(t=dp[i-1][j-1]<=dp[i][j-1]?dp[i-1][j-1]:dp[i][j-1])<= dp[i-1][j] ? t : dp[i-1][j];
dp[i][j]+=1;
}
}
}
return dp[len1][len2];
}
};
01背包
有 n 个物品和一个大小为 m 的背包. 给定数组 A 表示每个物品的大小和数组 V 表示每个物品的价值.
问最多能装入背包的总价值是多大?
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @return: The maximum size
*/
int backPack(int m, vector<int> &A) {
int cats=A.size();
int rows=m+1, cols=cats+1;
vector<vector<int>> dp(rows, vector<int>(cols,0));
for(int i=1; i<m+1;i++){
for(int j=1; j<cats+1; j++){
if(i>=A[j-1]){
dp[i][j]=max(dp[i-A[j-1]][j-1]+A[j-1],dp[i][j-1]);
}else{
dp[i][j]=dp[i][j-1];
}
}
}
int result=dp[m][cats];
dp.clear();
return result;
}
};