1 算法思想

算法分类

搜索算法主要分为:

暴力搜索+剪枝,枚举,广度优先搜索,深度优先搜索,二分查找,哈希查找, A*算法,两边向中间逼近,从中间向两边扩散等

1.1枚举

枚举: 最直白的搜索方式,依次尝试搜索空间中的所有解。可以在搜索过程中通过加强条件约束来减少搜索范围图。

例如: 百鸡问题

1.2广度优先搜索(BFS)

含义:遍历解答树时使每次状态转移时扩展出尽可能多的状态,并按照各状态出现顺序依次扩展它们。

表现:在解答树上表现为树的层次遍历。

适用:可用于求解最优问题。因为其搜索到的状态总是按照某个关键字递增(例如时间,倒杯次数等)。一旦问题中出现最少,最短,最优等关键字,

就需要考虑是否使用广度优先搜索。

实现: 一般用队列实现,用结构体保存每个状态,用标记数组防止无效搜索。

实现过程:

1)定义结构体用于保存每个状态,定义标记数组防止无效搜索

2)初始化第一个元素,并将该元素塞入队列中,设置第一个元素为已经访问

3)只要队列非空,得到并弹出队头元素,扩展得到新的元素,

对每个新元素,判断其如果满足约束条件并且是未遍历过的,

则更新新元素的状态,并将新元素塞入队列,设置新元素为已经访问过,

如果新元素是所求解,则直接返回

剪枝: 剪去解答树上不可能存在答案的子树。

1.3深度优先搜索(DFS)

含义: 优先遍历层次更深的状态,直到遇到一个状态节点不再拥有子树,则返回上一层,

访问其未被访问过的子树,直到解答树中所有状态被遍历完成。

适用: 深度优先搜索缺少广度优先搜索按层次递增顺序遍历的特性,深度优先搜索到的状态不再具有最优特性,深度优先搜索更多求解的是有解或者无解的问题。

实现: 通常使用递归实现。

实现过程:

1)扩展得到新元素,如果新元素不符合约束条件,则过滤该新元素;

2)基于当前状态更新得到新元素状态,判断新元素状态是否等于所求状态,如果是,设置结果标记为成功并直接返回;

3)否则,设置新元素为已经访问,递归处理,设置新元素为未访问(因为后续状态全部遍历完成,需要退回上层状态),如果结果标记为成功,则停止搜索

1.2 特点

1.3适用

1.4通用解法

广度优先搜索(BFS)算法:

1)定义结构体用于保存每个状态,定义标记数组防止无效搜索

2)初始化第一个元素,并将该元素塞入队列中,设置第一个元素为已经访问

3)只要队列非空,得到并弹出队头元素,扩展得到新的元素,

对每个新元素,判断其如果满足约束条件并且是未遍历过的,

则更新新元素的状态,并将新元素塞入队列,设置新元素为已经访问过,

如果新元素是所求解,则直接返回

深度优先搜索(DFS)算法:

1)扩展得到新元素,如果新元素不符合约束条件,则过滤该新元素;

2)基于当前状态更新得到新元素状态,判断新元素状态是否等于所求状态,如果是,设置结果标记为成功并直接返回;

3)否则,设置新元素为已经访问,递归处理,设置新元素为未访问(因为后续状态全部遍历完成,需要退回上层状态),如果结果标记为成功,则停止搜索

1.5经典例题讲解

广度优先搜索(BFS):

胜利大逃亡

我被魔王抓走,城堡是A*B*C的立方体,即A个B*C的矩阵,我被关在(0,0,0)位置,出口在(A-1,B-1,C-1),魔王在T分钟内回到城堡,

我每分钟能移动1个坐标。若走到出口恰遇魔王,也算成功。请输出多少分钟可以离开,不能则输出-1

代码:

typedef struct Stat                //定义结构体用于保存每个状态

{

int x,y,z;//坐标

int t;//从(0,0,0)到达该坐标的时间

}Stat;//保存当前节点的状态

int maze[N][N][N];//用于标识每一个坐标是0:路,1:墙

bool mark[N][N][N];// 定义标记数组防止无效搜索,用于标识该坐标是否已经搜索过,false:未搜索过,true:搜索过,便于剪枝

int goNext[][3] =

{1,0,0,

-1,0,0,

0,1,0,

0,-1,0,

0,0,1,

0,0,-1};//用于进行下一次6个可达状态的遍历

queue<Stat> queueStat;

//进行深度遍历,无需判断超时

int BFS(int a,int b,int c)

{

//只要队列不空,说明仍有状态需要遍历

while(!queueStat.empty())

{

//弹出当前状态,进行状态迁移

Stat stat = queueStat.front();

queueStat.pop();

//遍历6种状态,扩展得到新的元素

int x,y,z;

for(int i = 0 ; i < 6 ; i++)

{

x = stat.x + goNext[i][0];

y = stat.y + goNext[i][1];

z = stat.z + goNext[i][2];

//对每个新元素,判断其如果满足约束条件并且是未遍历过

// 判断是否仍在围墙中

//易错,这里城堡的位置是不能为a,因为这是数组,这样做就超过了

//if(x < 0 || x > a || y < 0 || y > b || z < 0 || z > c)

if(x <0 || x >= a || y < 0 || y >=b || z < 0 || z >= c )

{

continue;

}

//如果已经遍历过,则跳过

if(true==mark[x][y][z])

{

continue;

}

//如果下一个是墙,则跳过

if(1==maze[x][y][z])

{

continue;

}

//更新新元素的状态,并将新元素塞入队列,设置新元素为已经访问过

Stat statTemp;

statTemp.x = x;

statTemp.y = y;

statTemp.z = z;

statTemp.t = stat.t + 1;//所耗时间进行累加

//易错,更新剪枝状态

mark[x][y][z] = true;

//将新状态放入队列

queueStat.push(statTemp);

//如果新元素是所求解,则直接返回

//判断是否已经到达终点,则返回其所耗时间

if(a-1==x && b-1==y && c-1==z)

{

return statTemp.t;

}

}//for

}//while

return -1;//如果一直没有找到,返回-1

}

深度优先搜索(DFS)

Temple of the bone

有一个N*M的迷宫,起点S,终点D,墙X和地面,'.'表示路,0秒时,我从S出发,

每秒能走到4个与其相邻位置的任意一个,行走之后不能再次走入。

问:是否存在一条路径使主人公刚好在T秒走到D

代码

typedef struct Stat

{

int x,y;//横纵坐标

int t;//耗费时间

}Stat;

char maze[N][N];//保存迷宫元素

bool success;//设置是否找到的成功标记

//走下一个位置的数组

int goNext[][2] =

{0,1,

-1,0,

1,0,

0,-1

};

//深度优先搜索

void DFS(int x,int y,int t,int n,int m,int tLimit)

{

int i ;

// 扩展得到新元素

for(i = 0 ; i < 4 ; i ++)

{

int iXNext = x + goNext[i][0];

int iYNext = y + goNext[i][1];

// 如果新元素不符合约束条件,则过滤该新元素

//判定有无超过迷宫位置

if(iXNext < 1 || iXNext > n || iYNext < 1 || iYNext > m)

{

continue;

}

//判定是否是墙

if('X'==maze[iXNext][iYNext])

{

continue;

}

// 基于当前状态更新得到新元素状态,判断新元素状态是否等于所求状态,如果是,设置结果标记为成功并直接返回

//判定是否到达终点,并且时间要符合

if('D'==maze[iXNext][iYNext] && tLimit==(t + 1))

{

//易错,需要设置成功标记

success = true;

return;

}

//设置新元素为已经访问,递归处理,设置新元素为未访问(因为后续状态全部遍历完成,需要退回上层状态),如果结果标记为成功,则停止搜索

maze[iXNext][iYNext] = 'X';

//递归调用

DFS(iXNext,iYNext,t+1,n,m,tLimit);

//若其后续状态全部遍历完毕,返回上层状态,因为要搜索后续状态,因此再将墙改为普通状态

maze[iXNext][iYNext] = '.';

//易错,判断是否搜索成功

if(true==success)

{

return;

}

}//for

//如果一直遍历不到,则返回-1

return;

}

2 搜索系列

类别-编号

题目

遁去的1

16

找出已排序数组经过旋转后某个元素

给定一个排序后的数组,包含n个整数,但这个数组已经被旋转过很多次,次数不详。请编写代码找出数组中的某个元素。可以假定数组元素原先是按照从小到大的顺序排列的。

输入:

6(数组中元素个数) 0(寻找的值)

3 4 5 0 1 2

6 2

4 5 0 1 2 3

6 3

2 2 2 2 3 2

6 3

2 3 2 2 2 2

6 3

2 2 2 2 2 2

输出

3(输出元素在数组中的下标,如果找不到返回-1)

4

4

1

-1

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54349066

关键:

1 书上解法:

需要用中间元素和两边元素比较,确定哪一边是升序,然后进行搜索。

例子: 3 4 5 0 1 2

1)如果中间元素A[m] > 最左边元素A[l],说明左半部分是升序,判断查找值x

1.1)若A[l] <= x <= A[m],直接在左半部分寻找

1.2)否则,在右半部分寻找

例子: 4 5 0 1 2 3

2)如果A[m] < A[l],右半部分是升序,

2.1)如果A[m] <= x <= A[h],在右半部分寻找

2.2) 否则在左半部分寻找

例子: 2 2 2 2 3 2

2 3 2 2 2 2

3) 如果A[m] = A[l]

3.1)如果x = A[m],直接返回

3.2) 否则,3.2.1)如果A[h] != A[m],在右半部分寻找

3.2.2)如果A[h] = A[m],可能在左边也可能在右边(错,不要用顺序搜索,先搜索左边,再搜右边,根据是否查找到继续搜索,牛逼)

代码:

int binarySearchRotation(vector<int>& datas , int low , int high , int value)

{

if(datas.empty() || low < 0 || high < 0)

{

return -1;

}

int middle;

while(low <= high)

{

middle = low + (high - low) / 2 ;

//找到

if(datas.at(middle) == value)

{

return middle;

}

//左边有序

if( datas.at(low) < datas.at(middle) )

{

//查找值在左半部分

if( datas.at(low) <= value && value <= datas.at(middle) )

{

return binarySearchRotation(datas , low , middle - 1 , value);

}

else

{

return binarySearchRotation(datas , middle + 1, high , value);

}

}

//右边有序

else if( datas.at(low) > datas.at(middle) )

{

//查找值在右半部分

if( datas.at(middle) <= value && value <= datas.at(high) )

{

return binarySearchRotation(datas , middle + 1 , high ,value);

}

else

{

return binarySearchRotation(datas , low , middle - 1 , value);

}

}

//左边和中间值相同

else

{

//如果右边值不和中间值相同,搜索右半部分

if( datas.at(middle) != datas.at(high) )

{

return binarySearchRotation(datas , middle + 1 , high , value);

}

//如果左边,中间,右边所有的值相同,那么先搜左边如果左边搜索不到,搜索右边

else

{

int result = binarySearchRotation(datas , low , middle - 1 , value);

if( -1 == result)

{

result = binarySearchRotation(datas , middle + 1 , high , value);

}

return result;

}

}

}

//如果low > high,还没找到,说明不存在

return -1;

}

17

有个排序后的字符串数组,其中散布这一些空字符串,编写一个方法,找出给定字符串的位置

输入:

6(字符串个数) ba(待查找的字符串)

ab #(表示空字符串) # ba # ma

6 chao

ab # # ba # ma

输出:

3(待查找字符串下标,找不到返回-1)

-1

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54349154

分析:题目的意思应该是字符串数组已经排好序,但是里面混杂着空字符串,例如:

["ab" , " " , "ba" , " " , "ma"]

最简单的方式是暴力破解:遍历所有,顺序查找,时间复杂度为O(N)

另外一种方式就是:把所有字符串拼接成一个大的字符串:变成"ab ba ma",比如要查找"ba",

问题变成了字符串查找,字符串查找时间复杂度为O(N)的KMP算法

书上解法:早就应该想到,既然是搜索,肯定要跟二分搜索扯上关系。注意排好序的字符串,可以用

二分查找,可以用待查找的字符串str和中间字符串进行比较,如果遇到空字符串,就将中间

位置移动到距离其最近的非空字符串;如果距离两边的非空字符串一样近,就先右边,后左边,

如果找不到,继续寻找中间位置

代码:

const string EMPTY_STRING = "#";

int binarySearch(vector<string>& datas , int low , int high , string& value)

{

if(datas.empty() || low < 0 || high < 0 || value.empty())

{

return  -1;

}

//如果找不到,返回-1

if(low > high)

{

return -1;

}

int middle = low + (high - low)/2;

int left;

int right;

//如果中间字符串是空字符串,需要寻找到左右两侧中距离其最近的非空字符串,然后用二分查找

if(datas.at(middle).empty())

{

left = middle - 1;

right = middle + 1;

while(left >= low && right <= high)

{

//右侧字符串不空

if(!datas.at(right).empty())

{

middle = right;

break;

}

else if(!datas.at(left).empty())

{

middle = left;

break;

}

else

{

left--;

right++;

}

}

}

//找到位置后,下面用二分查找

int result = -1;

if(datas.at(middle) == value)

{

return middle;

}

//比较两个字符串,如果:查找字符串 < 中间字符串,即strcmp < 0,说明在左侧

else if( strcmp( value.c_str() , datas.at(middle).c_str() ) < 0 )

{

result = binarySearch(datas , low , middle - 1 ,value);

return result;

}

else

{

result = binarySearch(datas, middle + 1 , high , value);

return result;

}

}

18

设计一个方法,找出任意指定单词在一本书中的出现频率

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54578917

分析:这个明显是信息检索中倒排索引的使用。倒排索引需要使用链表数组和哈希来做。

但是可能存在一个问题:假设单词1和单词2通过哈希函数得到的哈希值相同,那么:

获取单词出现次数的时候,需要比较对于Java而言可以使用HashTable,

对于Python,它并没有自己的哈希函数,所以需要自己写。对于C++,存在

关键:

1 hash_map<string , int> wordToTimes;

#include <hash_map>

2 简单的题目一定要对输入参数检查

//易错,一定做判空处理

if(word.empty() || wordToTimes.empty())

{

return 0;

}

transform(word.begin() , word.end() , word.begin() , tolower);//先转小写后再查询

3

#include <algorithm>

//注意信息检索中全部存放转换为小写的

transform(word.begin() , word.end() , word.begin() , tolower);

代码:

hash_map<string , int> generateWordTable(vector<string>& words )

{

string word;

hash_map<string , int> wordToTimes;

for(vector<string>::iterator it = words.begin() ; it != words.end() ; it++)

{

word = *it;

//注意信息检索中全部存放转换为小写的

transform(word.begin() , word.end() , word.begin() , tolower);

hash_map<string , int>::iterator itFind = wordToTimes.find(word);

if( itFind != wordToTimes.end())

{

itFind->second++;

}

else

{

wordToTimes.insert(pair<string , int>(word , 1));

}

}

return wordToTimes;

}

int getFrequency(hash_map<string , int>& wordToTimes , string word)

{

//易错,一定做判空处理

if(word.empty() || wordToTimes.empty())

{

return 0;

}

transform(word.begin() , word.end() , word.begin() , tolower);//先转小写后再查询

hash_map<string , int>::iterator itFind = wordToTimes.find(word);

if( itFind != wordToTimes.end())

{

return itFind->second;

}

else

{

return 0;

}

}

19

设计一个算法,找出数组中两数之和为指定值的所有整数对。

输入:

8(数组元素个数n,接下来一行是输入的n个元素) 9(两数之和)

1 8 5 7 6 3 4 5

输出:

1 8,3 6,4 5

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54583254

分析:如果数组直接用无序的做,时间复杂度为O(n^2),对每个整数,遍历剩余整数。

如果先对数组排序,然后一个从左边,一个从右边,向中间遍历,时间复杂度为:排序时间复杂度O(NlogN),两边向中间遍历时间O(N),

所以最终时间为O(NlogN)。

因此,先排序,然后夹逼来做

代码:

vector< pair<int , int> > getPair(vector<int>& datas, int value)

{

vector< pair<int, int> > results;

if(datas.empty())

{

return results;

}

sort(datas.begin() , datas.end());

int low = 0;

int high = datas.size() - 1;

while(low < high)

{

//如果 左边+右边 > 和, 右边下标减少; 左边+右边 < 和 , 左边下标累加 ; 左边+右边= 和, 左边下标累加,右边下标累减

if( datas.at(low) + datas.at(high) > value )

{

high--;

}

else if( datas.at(low) + datas.at(high) < value )

{

low++;

}

else

{

pair<int , int> result(datas.at(low) , datas.at(high));

results.push_back(result);

high--;

low++;

}

}

return results;

}

20

有个内含单词的超大文本文件,给定任意两个单词,找出在这个文件中这两个单词的最短距离(也即相隔几个单词)。有办法在O(1)时间里完成搜索操作吗?解法的空间复杂度如何?

输入:

m a(n个待搜索的单词)

14(文本中单词个数)

c d a a b e m m r a e g g m

输出:

2(最短距离)

m r a(最短摘要,从搜索的单词1开始到搜索的单词2结尾)

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/54603976

关键:

1 书上解法:最简单的是遍历字符串列表,找到每个单词出现的下标,将属于同一个单词的下标集合以数组形式存放,然后将两个数组排序,

选取出自不同数组的连续差值最小的作为结果即可

比如: 对于单词数组  : c d a a b e m m r a e g g m

单词m 出现的下标集合:{6,7,13}

单词a               :{2,3,9}

标记数组:{2a,3a,6b,7b,9a,13b}

2     设字符串数组为A,遍历当前字符串数组,如果寻找到两个单词中其中一个,记录其下标为i,如果后续继续找到某个单词记录其下标j

如果A[i] = A[j],说明两个单词相同,则令j=-1,

否则,说明两个单词不相同,记录单词距离d=|j-i|,如果d < 最小单词距离minDis,更新minDis=d,minIndex1=i,minIndex2=j

不断移动两个单词的下标,记录最短距离和最短距离单词所在位

3 此题与之前的编程之美:最短摘要生成不同的是,最短摘要生成是通过:首先设置起始,截止指针begIndex,endIndex,遍历字符串找到一组下标begIndex,endIndex,

使得能够包含所有待查找字符串;

没有找到最短摘要,就endIndex++;

找到最短摘要,就begIndex++;       即让某个被查找的元素不再包含到最短摘要中,这样来促使endIndex继续移动发生变化

代码:

typedef struct Result

{

Result(){}

Result(int index1 , int index2 , int mDis , string& sResult):

_index1(index1),_index2(index2),_minDis(mDis),_searchResult(sResult){}

int _index1;//单词1的起始位置

int _index2;//单词2的起始位置

int _minDis;

string _searchResult;

}Result;

enum ArrayFlag{ARRAY1 , ARRAY2};

typedef struct Value

{

Value(int value, ArrayFlag flag):_value(value),_arrayFlag(flag){}

int _value;

ArrayFlag _arrayFlag;

bool operator < (const Value& other) const

{

return _value < other._value;

}

}Value;

Result search2(vector<string>& words , string& word1 , string& word2)

{

Result invalidResult(-1, -1 , -1, string(""));

if(words.empty() || word1.empty() || word2.empty() || word1 == word2)

{

return invalidResult;

}

vector<Value> indexs;

int size = words.size();

for(int i = 0 ; i < size ; i++)

{

//每当找到一个单词时,就进行比较

if( words.at(i) == word1 )

{

indexs.push_back(Value( i , ARRAY1));

}

else if( words.at(i) == word2 )

{

indexs.push_back(Value( i , ARRAY2));

}

}

sort(indexs.begin() , indexs.end());

//排好序遍历相邻两个来自不同数组的元素

int length = indexs.size();

int minDis = INT_MAX;

Result result;

for(int i = 1 ; i < length ; i++)

{

//两个不同的数组

if(indexs.at(i-1)._arrayFlag != indexs.at(i)._arrayFlag)

{

int dis = abs( indexs.at(i-1)._value - indexs.at(i)._value);

if(dis < minDis)

{

minDis = dis;

result._minDis = minDis;

result._index1 = indexs.at(i-1)._value;

result._index2 = indexs.at(i)._value;

}

}

}

//如果单词1在前面

int beginIndex = result._index1 < result._index2 ? result._index1 : result._index2;

int endIndex = result._index1 > result._index2 ? result._index1 : result._index2;

stringstream stream;

for(int i = beginIndex ; i <= endIndex ; i++)

{

stream << words.at(i) << " ";

}

result._searchResult = stream.str();

return result;

}

21

3Sum

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:

[

[-1, 0, 1],

[-1, -1, 2]

]

triplets:三元组

输入:

15

-4 -2 -2 -2 0 1 2 2 2 3 3 4 4 6 6

6

-1 0 1 2 -1 -4

6

0 0 0 0 0 0

6

-1 -1 -1 -1 2 2

1

0

2

0 0

输出:

-4-2 6,-4 0 4 , -4 1 3, -4 2 2 , -2 -2 4 , -2 0 2

-1 0 1, -1 -1 2

0 0 0

-1 -1 2

no result

no result

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54782732

分析:之前一道题是计算两个数的和,然后是从两边向中间逼近。

如果采用暴力破解:那么需要一个三层循环,时间复杂度为O(n^3)

如果先排序,从小到大,那么如果假设: a < b < c,必定有c大于0,a小于0,至于b=-a-c

如果去遍历a,c从两头向中间,并且设定一个哈希表,那么查询b在哈希表中的时间是O(1),

则时间复杂度为O(n^2)。

一种更简单的方法:先排序,根据a+b+c=0,所以b=-(a+c)

初始时:设定a是最左边元素,c是最右边元素,假设数组为A

计算b=-(a+c),

如果b在哈希表中,说明成立,判断该三元组如果不重复就直接输出;

否则,说明找不到。  这两种情况都需要使得最左边下标累加,最右边下标累减。因为a和c分别是最小,最大,且当前情况都已经匹配过

如果出现: b > c,说明a太小,使得条件不满足,则使得左边下标累加

b < a,说明c太大,                      右边下标累减

整体时间复杂度为O(NlogN)

发现hash_map不能用:Line 17: 'hash_map' was not declared in this scope

如果b在哈希表hash<int ,int>即<值,出现次数>中b

果然发现递归超时。

一种解法:根据两数和的想法,先对数组排序,首先确定第一个数a,然后设定两数和为-a,则两数和采用从两头向中间逼近的方法,

两数和时间复杂度O(n),遍历数组中每个元素作为第一个数时间复杂度为O(n),总时间复杂度为O(n^2)。

关键:

1 根据两数和的想法,先对数组排序,首先确定第一个数a,然后设定两数和为-a,则两数和采用从两头向中间逼近的方法,

两数和时间复杂度O(n),遍历数组中每个元素作为第一个数时间复杂度为O(n),总时间复杂度为O(n^2)。

代码:

class Result

{

public:

Result(){}

Result(int min , int mid , int max):_min(min),_mid(mid),_max(max){}

bool operator < (const Result& result) const //仿函数,用于set排序

{

if(_min != result._min)

{

return _min < result._min ;

}

else if(_mid != result._mid)

{

return _mid < result._mid;

}

else

{

return _max < result._max;

}

}

int _min;

int _mid;

int _max;

};

class Solution {

public:

//计算两数之和,结果可能多个。如何去重?已经有一个数被使用了,这个数不能出现在求两数之和的结果中,遇到该下标直接跳过

void twoSum(vector<int>& nums , int value , int selectIndex, set<Result, less<Result> >& results)

{

if(nums.empty())

{

return ;

}

int sum;

int size = nums.size();

int low = 0;

int high = size - 1;

int minValue , midValue , maxValue;

while(low < high)

{

//如果左边的数字等于已经选择的数字,则low++

if(selectIndex == low)

{

low++;

}

else if(selectIndex == high)

{

high--;

}

//如果发现不满足,则退出

if(low >= high)

{

break;

}

//如果两数之和小于目标值,则令low++;两数之和大于目标值,high--;如果两数之和等于目标值,则low++,high--

sum = nums.at(low) + nums.at(high);

if(sum < value)

{

low++;

}

else if(sum > value)

{

high--;

}

//找到了,存入结果集,存入的结果集需要确定三者的大小

else

{

minValue = min( nums.at(low) ,nums.at(high) , nums.at(selectIndex) );

maxValue = max( nums.at(low) ,nums.at(high) , nums.at(selectIndex) );

midValue = sum + nums.at(selectIndex) - minValue - maxValue;

Result result(minValue , midValue , maxValue);

results.insert(result);

low++;

high--;

}

}

}

/*

本质上确定第一个数之后,随后两个数的确定可以采用两数之和的方法(从两头向中间逼近),但要去除掉重复的,判重部分单独提取一个方法。

*/

vector<vector<int>> threeSum(vector<int>& nums) {

vector<vector<int>> resultVector;

//遍历每一个数作为第一个数,确定其余两数之和

if(nums.empty())

{

return resultVector;

}

//先排序

sort(nums.begin() , nums.end());

int size = nums.size();

int a;

int target;

int selectIndex;

set<Result, less<Result> > results;

for(int i = 0 ; i < size ; i++)

{

//依次选择第一个数,那么第一个数就不能再作为第二个数,第三个数

a = nums.at(i);

selectIndex = i;

//两个数的目标和为: -a

target = -a;

twoSum(nums , target , selectIndex , results);

}

//计算出结果后,输出结果

for(set<Result , less<Result> >::iterator it = results.begin() ; it != results.end() ; it++)

{

vector<int> resultVec;

resultVec.push_back(it->_min);

resultVec.push_back(it->_mid);

resultVec.push_back(it->_max);

resultVector.push_back(resultVec);

}

return resultVector;

}

};

22

3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

For example, given array S = {-1 2 1 -4}, and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

翻译:

这个是找到三个数的和要最接近给定值。

输入:

4(数组元素个数) 1(三数和的目标值)

-1 2 1 -4

6 0

-2 -1 0 1 1 2

输出:

2

0

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54782805

分析:这个是找到三个数的和要最接近给定值。与之前三数和不同的是这里肯定要修改判定条件。要维护一个最接近给定值的数值,每当

有新的最接近的数值的时候,就更新。

暴力破解:一个三层循环,分别对每个数字遍历,计算三数和的结果,取最接近的,时间复杂度为O(n^3)

两数和思想:如果选中一个数a作为给定值,那么作为目标的两数和-a最接近的部分,所以似乎没有思路。

简化问题:如果是一个数组求两数和最接近指定数值,求这个两数和t,该怎么做?

设两个下标分别为low,high,数组为A,sum=A[low] + A[high],设定两数和sum和target之间的差值diff=INT_MAX,

sum > t:则sum可能是结果集,假设此时low++,只会使得sum更大,所以不对,因此是high--,如果|sum-target| < diff,则diff=|sum-target|,记录两数和sum

sum < t:则sum可能是结果集,此时应该low++,同时判定是否需要更新结果集

sum = t:则sum就是结果集,直接输出

因为此题是最接近,因此答案应该是一个,如果有多个也输出一个

经过上述分析:此时三数和最接近也可以用上述二数和最接近的思路来做,时间复杂度仍为O(n^2)

关键:

1 简化问题:如果是一个数组求两数和最接近指定数值,求这个两数和t,该怎么做?

设两个下标分别为low,high,数组为A,sum=A[low] + A[high],设定两数和sum和target之间的差值diff=INT_MAX,

sum > t:则sum可能是结果集,假设此时low++,只会使得sum更大,所以不对,因此是high--,如果|sum-target| < diff,则diff=|sum-differget|,

记录两数和sum

sum < t:则sum可能是结果集,此时应该low++,同时判定是否需要更新结果集

sum = t:则sum就是结果集,直接输出

因为此题是最接近,因此答案应该是一个,如果有多个也输出一个

经过上述分析:此时三数和最接近也可以用上述二数和最接近的思路来做,时间复杂度仍为O(n^2)

代码:

class Solution {

public:

//计算两数之和,结果可能多个。如何去重?已经有一个数被使用了,这个数不能出现在求两数之和的结果中,遇到该下标直接跳过

int twoSum(vector<int>& nums , int value , int selectIndex)

{

if(nums.empty())

{

return 0;

}

int sum;

int size = nums.size();

int low = 0;

int high = size - 1;

int minDiff = INT_MAX;

int diff;

int resultSum;

while(low < high)

{

//如果左边的数字等于已经选择的数字,则low++

if(selectIndex == low)

{

low++;

}

else if(selectIndex == high)

{

high--;

}

//如果发现不满足,则退出

if(low >= high)

{

break;

}

//如果两数之和小于目标值,则令low++;两数之和大于目标值,high--;如果两数之和等于目标值,则low++,high--

sum = nums.at(low) + nums.at(high);

diff = abs(sum - value);

//如果遇到更接近给定值的两数和,记录结果

if(diff < minDiff)

{

resultSum = sum;

minDiff = diff;

}

if(sum < value)

{

low++;

}

else if(sum > value)

{

high--;

}

//找到了,说明找到最接近的,直接输出

else

{

break;

low++;

high--;

}

}

return resultSum;

}

int threeSumClosest(vector<int>& nums, int target) {

//数据为空,返回为0

if(nums.empty())

{

return 0;

}

//先排序

sort(nums.begin(), nums.end());

int size = nums.size();

int realTarget;

int sum;

int resultSum;

int diff;

int minDiff = INT_MAX;

int threeSumResult;

for(int i = 0 ; i < size ; i++)

{

realTarget = target - nums.at(i);

sum = twoSum(nums , realTarget , i);

threeSumResult = sum + nums.at(i);

diff = abs(threeSumResult  - target);

if(diff < minDiff)

{

minDiff = diff;

resultSum = threeSumResult;

}

}

return resultSum;

}

};

23

4Sum

Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note: The solution set must not contain duplicate quadruplets.

For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.

输入:

6(数组元素个数) 0(目标和)

1 0 -1 0 -2 2

9 12

0 4 -5 2 -2 4 2 -1 4

输出:

-1 0 0 1, -2 -1 1 2, -2 0 0 2

0 4 4 4, 2 2 4 4

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54798862

分析:

用3Sum来做。罗列第一个数和第二个数,时间复杂度为O(n^3)

关键:

1 4Sum用3Sum来做。罗列第一个数和第二个数,时间复杂度为O(n^3)

for(int i = 0 ; i < size - 2 ; i++)

{

int target_3 = target - nums.at(i);

for(int j = i + 1 ; j < size - 1; j++)

{

int target_2 = target_3 - nums.at(j);

int low = j + 1;

int high = size - 1;

while(low < high)

{

sum = nums.at(low) + nums.at(high);

if(sum < target_2)

{

low++;

}

else if(sum > target_2)

{

high--;

}

else

{

Result result(nums.at(i) , nums.at(j) , nums.at(low) , nums.at(high));

setResult.insert(result);

low++;

high--;

}

}

}

}

代码:

typedef struct Result

{

Result(){}

Result(int min ,int mid1 , int mid2 , int max):_min(min),_mid1(mid1),_mid2(mid2),_max(max){}

bool operator < (const Result& result) const

{

if(_min != result._min)

{

return _min < result._min;

}

else if(_mid1 != result._mid1)

{

return _mid1 < result._mid1;

}

else if(_mid2 != result._mid2)

{

return _mid2 < result._mid2;

}

else

{

return _max < result._max;

}

}

int _min;

int _mid1;//次最小

int _mid2;//次最大

int _max;

}Result;

class Solution {

public:

vector<vector<int>> fourSum(vector<int>& nums, int target)

{

vector<vector<int>> results;

if(nums.empty() || nums.size() < 4)

{

return results;

}

int size = nums.size();

sort(nums.begin() , nums.end());

int sum;

set<Result , less<Result> > setResult;

//这里的关键是罗列的时候:我已经实现罗列的a<=b,后续确定的另外两个数c,d有:a <= b <= c <= d

//这样罗列比如:a=A[1], b=A[3],那么是否c可以为A[2]?不可以,已经假定了顺序。那么也不会存在判重的问题

for(int i = 0 ; i < size - 2 ; i++)

{

int target_3 = target - nums.at(i);

for(int j = i + 1 ; j < size - 1; j++)

{

int target_2 = target_3 - nums.at(j);

int low = j + 1;

int high = size - 1;

while(low < high)

{

sum = nums.at(low) + nums.at(high);

if(sum < target_2)

{

low++;

}

else if(sum > target_2)

{

high--;

}

else

{

Result result(nums.at(i) , nums.at(j) , nums.at(low) , nums.at(high));

setResult.insert(result);

low++;

high--;

}

}

}

}

//返回结果

for(set<Result , less<Result> >::iterator it = setResult.begin() ; it != setResult.end() ; it++)

{

vector<int> vecResult;

//vector<int>{nums[i],nums[j],nums[left],nums[right]}

vecResult.push_back(it->_min);

vecResult.push_back(it->_mid1);

vecResult.push_back(it->_mid2);

vecResult.push_back(it->_max);

results.push_back(vecResult);

}

return results;

}

};

24

Remove Element

Given an array and a value, remove all instances of that value in place and return the new length.

Do not allocate extra space for another array, you must do this in place with constant memory.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.

Example:

Given input array nums = [3,2,2,3], val = 3

Your function should return length = 2, with the first two elements of nums being 2.

输入:

4(元素个数) 3(待删除元素)

3 2 2 3(所有数组元素)

4 1

3 2 2 3

输出:

2(新数组的长度)

4

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54848487

分析:

此题实际上就是删除元素为指定值的元素,数组事先是无序的。

一种简单方法是:先排序,排序结束后通过二分查找元素上下区间,删除区间内元素,时间复杂度为O(N*logN)

如果不排序,删除指定元素,每次从前向后移动,找到指定元素后,将该元素后面所有元素向前移动一位,

遍历元素的时间复杂度为O(N),找到元素后,后面所有元素向前移动时间复杂度为O(N),总的时间复杂度为O(N*N)

lower_bound:查找元素第一个出现的位置,或者如果没有该元素,查找大于该元素的位置,使得将元素插入数组后数组仍然有序

upper_bound:查找大于元素x的第一个位置,使得如果将待查找元素插入在该位置后,该数组仍然有序

代码:

class Solution {

public:

int removeElement(vector<int>& nums, int val) {

if(nums.empty())

{

return 0;

}

//排序

sort(nums.begin() , nums.end());

//查找>=元素的第一个出现的位置,位置是迭代器

vector<int>::iterator low = lower_bound(nums.begin() , nums.end() , val);

//超找>元素第一个出现的位置

vector<int>::iterator high = upper_bound(nums.begin() , nums.end() , val);

//删除元素

nums.erase(low , high);

int length = nums.size();

//print(nums);

return length;

}

};

25

Search in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

分析:

这是程序员面试金典的一道题目。是在旋转数组中查找一个元素。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54926088

这是程序员面试金典的一道题目。是在旋转数组中查找一个元素。

具体参见题目16

26

Search for a Range

Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,

Given [5, 7, 7, 8, 8, 10] and target value 8,

return [3, 4].

输入:

6(数组元素个数) 8(待查找元素)

5 7 7 8 8 10

6 12

5 7 7 8 8 10

1 1

1

2 2

2 2

输出

3 4

-1 -1

0 0

0 1

Leeode

https://blog.csdn.net/qingyuanluofeng/article/details/54926758

分析:

这是二分查找的lower_bound和upper_bound的问题

关键:

1vector<int> results(2 , -1);//vector(n,val)

2           //找不到

if(-1 == low)

{

vector<int> results(2 , -1);//vector(n,val)

return results;

}

//如果找到,但是只有一个元素

else

{

vector<int> results;

results.push_back(low);

results.push_back(high - 1);

return results;

}

3 在upper_bound中,

//low == high时,如果找到,就返回

if(nums.at(low) > target)

{

return low;

}

//如果发现找不到,就返回low+1(最后一定low为数组长度)

else

{

return low + 1;

}

代码:

class Solution {

public:

//寻找到第一个>=target的位置index,使得即使该元素找不到,插入该元素也有序

int lower_bound(vector<int>& nums , int target)

{

if(nums.empty())

{

return -1;

}

int low = 0;

int high = nums.size() - 1;

int mid;

while(low < high)

{

mid  = low + (high - low) / 2;

//中间大于目标值,目标值,mid可能是结果,继续在左半部分寻找

if(nums.at(mid) >= target)

{

high = mid;

}

//中间值 < 目标值,mid不可能是结果,在右半部分寻找

else

{

low = mid + 1;

}

}

//low == high时,如果找到,就返回

if(nums.at(low) == target)

{

return low;

}

else

{

return -1;

}

}

//找到第一个>target的元素的下标

int upper_bound(vector<int>& nums , int target)

{

if(nums.empty())

{

return -1;

}

int low = 0;

int high = nums.size() - 1;

int mid;

while(low < high)

{

mid  = low + (high - low) / 2;

//中间大于目标值,目标值,mid可能是结果,需要在左半部分寻找

if(nums.at(mid) > target)

{

high = mid;

}

//中间值 <= 目标值,mid不可能是结果

else

{

low = mid + 1;

}

}

//low == high时,如果找到,就返回

if(nums.at(low) > target)

{

return low;

}

//如果发现找不到,就返回low+1(最后一定low为数组长度)

else

{

return low + 1;

}

}

vector<int> searchRange(vector<int>& nums, int target) {

int low = lower_bound(nums , target);

int high = upper_bound(nums , target);

//找不到

if(-1 == low)

{

vector<int> results(2 , -1);//vector(n,val)

return results;

}

//如果找到,但是只有一个元素

else

{

vector<int> results;

//如果只有一个元素,那么high = low + 1

if(-1 == high)

{

high = low + 1;

}

results.push_back(low);

results.push_back(high - 1);

return results;

}

}

};

27

Search Insert Position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.

[1,3,5,6], 5 → 2

[1,3,5,6], 2 → 1

[1,3,5,6], 7 → 4

[1,3,5,6], 0 → 0

输入:

4 5

1 3 5 6

4 2

1 3 5 6

4 7

1 3 5 6

4 0

1 3 5 6

输出

2

1

4

0

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54927050

分析:

这是二分查找的lowwer_bound的问题。

关键:

1 lowwer_bound:

//low == high时,如果找到,就返回

if(nums.at(low) >= target)

{

return low;

}

//说明是数组最后一个元素,返回low+1

else

{

return low + 1;

}

代码:

class Solution {

public:

int lower_bound(vector<int>& nums , int target)

{

if(nums.empty())

{

return -1;

}

int low = 0;

int high = nums.size() - 1;

int mid;

while(low < high)

{

mid  = low + (high - low) / 2;

//中间大于目标值,目标值,mid可能是结果,继续在左半部分寻找

if(nums.at(mid) >= target)

{

high = mid;

}

//中间值 < 目标值,mid不可能是结果,在右半部分寻找

else

{

low = mid + 1;

}

}

//low == high时,如果找到,就返回

if(nums.at(low) >= target)

{

return low;

}

//说明是数组最后一个元素,返回low+1

else

{

return low + 1;

}

}

int searchInsert(vector<int>& nums, int target) {

int high = lower_bound(nums , target);

return high;

}

};

28

Valid Sudoku

Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.

The Sudoku board could be partially filled, where empty cells are filled with the character '.'.

A partially filled sudoku which is valid.

Note:

A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.

分析:

实质就是根据现有数独中已经填充的数字,计算是否有解。

数独中每一行和每一列必须包含1~9的数字

3*3的数组中必须包含1~9每个数字。

输入:

9(数独的长度,宽度与之相等)

53..7....

6..195...

.98....6.

8...6...3

4..8.3..1

7...2...6

.6....28.

...419..5

....8..79

输出:

yes

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54928387

分析:

实质就是根据现有数独中已经填充的数字,计算是否有解。

数独中每一行和每一列必须包含1~9的数字

3*3的数组中必须包含1~9每个数字。

此题关键是从何处开始遍历,

判断是否能够组成数组:采用每横或每竖列是否每个数字只出现一次,对于每个棋盘判断每个数字是否只出现一次;

一旦不符合,重新尝试填新的数字。

实际上就是递归来做。

关键是填充新的数字必须满足已有条件:

1:填充的数字已有出现次数不能超过总数

题目中说判断一个数独棋盘是否有效,不需要一定有解,只需要判定该棋盘是否满足其规则

采用暴力破解:

遍历每一行,每一列分别看每个元素是否出现次数<=1次,

关键:

1 判断子棋盘是否有效,可以遍历一遍棋盘,每次计算出子棋盘的编号k=i /3 * 3 + j / 3

例如(0,5)在第2个棋盘中,对应下标为1

for(int i = 0 ; i < size ; i++)

{

for(int j = 0 ; j < size ; j++ )

{

if('.' == board.at(i).at(j))

{

continue;

}

//计算子棋盘编号

subBoard = i / 3 * 3 + j /3 ;

num = board[i][j] - '0' - 1;//多减1是因为下标从0开始

if(usedRow[i][num] || usedCol[j][num] || usedSubBoard[subBoard][num])

{

return false;

}

usedRow[i][num] = usedCol[j][num] = usedSubBoard[subBoard][num] = 1;

}

}

代码:

class Solution

{

public:

bool isValidSudoku(vector<vector<char> > &board)

{

if(board.empty())

{

return false;

}

int size = board.size();

int usedRow[9][9] = {0};

int usedCol[9][9] = {0};

int usedSubBoard[9][9] = {0};

int subBoard;

int num;

for(int i = 0 ; i < size ; i++)

{

for(int j = 0 ; j < size ; j++ )

{

if('.' == board.at(i).at(j))

{

continue;

}

//计算子棋盘编号

subBoard = i / 3 * 3 + j /3 ;

num = board[i][j] - '0' - 1;//多减1是因为下标从0开始

if(usedRow[i][num] || usedCol[j][num] || usedSubBoard[subBoard][num])

{

return false;

}

usedRow[i][num] = usedCol[j][num] = usedSubBoard[subBoard][num] = 1;

}

}

return true;

}

};

29

Sudoku Solver

Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character '.'.

You may assume that there will be only one unique solution.

A sudoku puzzle...

...and its solution numbers marked in red.

分析:

这是搜索是否有解的问题,

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54930149

分析:

这是搜索是否有解的问题,广度优先搜索最优解,深度优先搜索确定是否有解。因此本题应该用深度优先搜索。

看题目,如果摆放新的元素不成功,应该是要回溯的。因此,此题应该是回溯来做。

每一次尝试摆放一个1~9中的某个元素,如果摆放不成功,就用另一个元素替换,如果最终棋盘摆满了,就输出结果。

如何判定没有结果,如果

1判断是否满足可行解,只需要当前board[i][j]元素为c是否在行号,列号,子棋盘摆放过

判断子棋盘上的9个元素是否与给定元素重复,先确定 子棋盘的行号=行号

给定位置(row,jcol)计算对应子棋盘的行号(x,y)

x = 3 * (row / 3)

y = 3 * (col / 3)

子棋盘编号 = 3 *(row / 3) + col /3 = 3 + 2 = 5,行号确定大的子棋盘编号,列号确定小的子棋盘编号

子棋盘元素下标 = 3 * (col / 3) + col % 3 = 3 * 2 + 8 % 3 = 8,其实就是将列分成3等份,然后取余数

比如给定元素(5,8),对应第6子棋盘中(编号为5)中第8个元素

这里由于采用i为0~8,i默认为列号

则新的子棋盘编号=board[ 3 * (row / 3) + i / 3 ][3 * (col / 3) + i % 3]

subBoardIndex = 3 * (row / 3) + i / 3;

index = 3 * (col / 3) + i % 3;

代码:

class Solution {

public:

bool isValidSudoku(vector<vector<char> > &board , int row  , int col , char c)

{

if(board.empty())

{

return false;

}

int size = board.size();

int subBoardIndex;

int index;

for(int i = 0 ; i < 9 ; i++)

{

//判断同一列上是否重复

if(board[i][col] != '.' && board[i][col] == c)

{

return false;

}

//判断同一行上是否重复

if(board[row][i] != '.' && board[row][i] == c)

{

return false;

}

/*

判断子棋盘上的9个元素是否与给定元素重复,先确定 子棋盘的行号=行号

给定位置(row,jcol)计算对应子棋盘的行号(x,y)

x = 3 * (row / 3)

y = 3 * (col / 3)

子棋盘编号 = 3 *(row / 3) + col /3 = 3 + 2 = 5,行号确定大的子棋盘编号,列号确定小的子棋盘编号

子棋盘元素下标 = 3 * (col / 3) + col % 3 = 3 * 2 + 8 % 3 = 8,其实就是将列分成3等份,然后取余数

比如给定元素(5,8),对应第6子棋盘中(编号为5)中第8个元素

这里由于采用i为0~9,i默认为列号

则新的子棋盘编号=board[ 3 * (row / 3) + i / 3 ][3 * (col / 3) + i % 3]

*/

subBoardIndex = 3 * (row / 3) + i / 3;

index = 3 * (col / 3) + i % 3;

if(board[subBoardIndex][index] != '.' && board[subBoardIndex][index] == c)

{

return false;

}

}

return true;

}

bool isSolved(vector<vector<char>>& board)

{

if(board.empty())

{

return false;

}

int size = board.size();

for(int i = 0 ; i < size ; i++)

{

for(int j = 0 ; j < size ; j++ )

{

if('.' == board.at(i).at(j))

{

//尝试在空白的区域处摆放下一个元素,这里直接用cha

for(char c = '1' ; c <= '9' ; c++)

{

//如果摆放有效,继续处理

if(isValidSudoku(board , i , j , c))

{

board.at(i).at(j) = c;

//牛逼,直接用递归判断下一次是否摆放成功

if(isSolved(board))

{

return true;

}

else

{

board.at(i).at(j) = '.';

}

}

}

//如果一直没有得到结果,说明无效

return false;

}

}

}

return true;

}

};

30

Sort Colors

Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.

Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

Note:

You are not suppose to use the library's sort function for this problem.

click to show follow up.

Follow up:

A rather straight forward solution is a two-pass algorithm using counting sort.

First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.

Could you come up with an one-pass algorithm using only constant space?

分析:颜色摆放问题。红白蓝三种颜色代表的数组,分别对应012,现在要使得

数组中相同颜色的相邻。不能使用系统自带的排序函数。

输入:

8(数组元素个数)

0 1 1 2 1 0 0 2

输出:

0 0 0 1 1 1 2 2

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55000030

关键:

1

1】如果遇到把A[i] == 2的判断放在前面,那么最右边的元素能够交换的是0或1,

1.1】如果交换的是0,那么后续 A[i] == 0的条件会处理;然后0会和最左边的1交换(2不可能,因为如果可能遇到2的话之前已经处理过了)

1.2】如果交换的是1,那么后续A[i] == 0的条件不会处理,i++

因此上述情况都会使得变成0..01..12..2有序

2】如果把A[i] == 0判断放在前面,那么可能当前A[i]会和2或者1交换

2.1】如果交换的是2,那么把2放到了i的位置,下面A[i] == 2的判断会成立,然后该2会和最右边的0或1交换,如果此时最右边为0

那么交换后i的位置又变成0,但是不会再处理这种情况,造成0的位置不正确

也就是说:A[i] == 0判断放在前面,如果和2交换,2再和最右边的0交换,此时为0不会再处理;

A[2] == 2判断放在前面,如果和0交换,0会和最左边的1交换,不影响顺序

2

int low = 0;

int high = size - 1;

for(int i = low ; i <= high ; i++)

{

//这里带来一个问题是最右边如果本来就为2,就少了一个2的交换。这里如果两个交换元素都是2,则交换后原位置仍为2

//然后原位置和新的最右边元素继续交换,直到最右边元素不是2,这样交换完了之后就达到了要求

//注意2的判断需要放在0的前面,因为:2不断与最右边元素交换完了之后可能最右边元素恰好为0,然后后续进行0的交换

while(2 == nums.at(i) && i < high)

{

swap(nums.at(i) , nums.at(high--));

}

//碰到0,放在最左边,并更新low,之所以用while且i不变就是为了防止两个元素都是0,交换后了之后,没有改变,所以和后面的元素交换

while(0 == nums.at(i) && i > low)

{

swap(nums.at(i) , nums.at(low++));

}

}

代码:

class Solution {

public:

void sortColors(vector<int>& nums) {

if(nums.empty() || nums.size() == 1)

{

return ;

}

int size = nums.size();

int low = 0;

int high = size - 1;

for(int i = low ; i <= high ; i++)

{

//这里带来一个问题是最右边如果本来就为2,就少了一个2的交换。这里如果两个交换元素都是2,则交换后原位置仍为2

//然后原位置和新的最右边元素继续交换,直到最右边元素不是2,这样交换完了之后就达到了要求

//注意2的判断需要放在0的前面,因为:2不断与最右边元素交换完了之后可能最右边元素恰好为0,然后后续进行0的交换

while(2 == nums.at(i) && i < high)

{

swap(nums.at(i) , nums.at(high--));

}

//碰到0,放在最左边,并更新low,之所以用while且i不变就是为了防止两个元素都是0,交换后了之后,没有改变,所以和后面的元素交换

while(0 == nums.at(i) && i > low)

{

swap(nums.at(i) , nums.at(low++));

}

}

}

};

31

Word Search

Given a 2D board and a word, find if the word exists in the grid.

The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.

For example,

Given board =

[

['A','B','C','E'],

['S','F','C','S'],

['A','D','E','E']

]

word = "ABCCED", -> returns true,

word = "SEE", -> returns true,

word = "ABCB", -> returns false.

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55002974

32

Search in Rotated Sorted Array II

Follow up for "Search in Rotated Sorted Array":

What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Write a function to determine if a given target is in the array.

The array may contain duplicates.

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55006880

33

Best Time to Buy and Sell Stock

Contributors: Admin

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Example 1:

Input: [7, 1, 5, 3, 6, 4]

Output: 5

max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)

Example 2:

Input: [7, 6, 4, 3, 1]

Output: 0

In this case, no transaction is done, i.e. max profit = 0.

分析:给定一个数组,模拟股票价格,要求获取最大利润。也就是从数组中选取两个元素,并且满足较小的元素在前面,较大的元素在后面,

求这样一个差值最大的两个元素。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55227456

34

Best Time to Buy and Sell Stock II

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like

(ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple

transactions at the same time (ie, you must sell the stock before you buy again).

分析:此题的意思是允许多次买入后再抛出股票。每次买入股票前必须先抛出之前买的。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55229904

35

Word Ladder

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

Only one letter can be changed at a time.

Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

For example,

Given:

beginWord = "hit"

endWord = "cog"

wordList = ["hot","dot","dog","lot","log","cog"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",

return its length 5.

Note:

Return 0 if there is no such transformation sequence.

All words have the same length.

All words contain only lowercase alphabetic characters.

You may assume no duplicates in the word list.

You may assume beginWord and endWord are non-empty and are not the same.

分析:这是求最短字符串长度。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55271936

36

Surrounded Regions

Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'.

A region is captured by flipping all 'O's into 'X's in that surrounded region.

For example,

X X X X

X O O X

X X O X

X O X X

After running your function, the board should be:

X X X X

X X X X

X X X X

X O X X

输入:

4(行) 4(列)

X X X X

X O O X

X X O X

X O X X

输出:

X X X X

X X X X

X X X X

X O X X

关键

1 分析:此题实际上找到四周都是"X"的"O",并把这些"O"替换为"X"。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55353384

37

Find Minimum in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.

You may assume no duplicate exists in the array.

分析:找到旋转数组中最小的元素。之前是做了找到旋转数组中某个元素是否存在。

这里假设没有重复。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56025453

38

Find Peak Element

A peak element is an element that is greater than its neighbors.

Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.

The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.

You may imagine that num[-1] = num[n] = -∞.

For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

click to show spoilers.

Credits:

Special thanks to @ts for adding this problem and creating all test cases.

分析:题目是为了寻找一个高峰元素,所谓高峰元素要大于两边元素,如果有多处高峰,返回其中任意的一个下标。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56047747

39

Two Sum II - Input array is sorted

Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution and you may not use the same element twice.

Input: numbers={2, 7, 11, 15}, target=9

Output: index1=1, index2=2

分析:在给定升序的数组中,返回两个相加和等于指定值得下标,下标都是从1开始的,第一个下标

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56276361

40

Number of Islands

Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Example 1:

11110

11010

11000

00000

Answer: 1

Example 2:

11000

11000

00100

00011

Answer: 3

分析:这个实际上就是求被水(0)分割的1的块数

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56304174

41

Minimum Size Subarray Sum

Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.

For example, given the array [2,3,1,2,4,3] and s = 7,

the subarray [4,3] has the minimal length under the problem constraint.

click to show more practice.

More practice:

If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56485513

42

Contains Duplicate

Given an array of integers, find if the array contains any duplicates.

Your function should return true if any value appears at least twice in the array,

and it should return false if every element is distinct.

分析:判断数组是否含有重复元素。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56495258

43

Contains Duplicate II

Given an array of integers and an integer k, find out whether there are two distinct

indices i and j in the array such that nums[i] = nums[j] and the absolute difference

between i and j is at most k.

分析:给定整数和整数k,找到是否有两个不同的下标i和j,使得nums[i]=nums[j],并且i和j的查找最多不超过k。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56495697

44

Contains Duplicate III

Given an array of integers, find out whether there are two distinct indices i and j

in the array such that the absolute difference between nums[i] and nums[j] is at most t

and the absolute difference between i and j is at most k.

分析:也就是说要寻找任意元素对应的下标i和j,满足i和j的差的绝对值<=k,两个数值的差值<=t

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56498897

45

First Bad Version

You are a product manager and currently leading a team to develop a new product. Unfortunately,

the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions

after a bad version are also bad.

Suppose you have n versions [1, 2, ..., n] and you want to find out the first bad one,

which causes all the following ones to be bad.

You are given an API bool isBadVersion(version) which will return whether version is bad.

Implement a function to find the first bad version. You should minimize the number of calls to the API.

分析:发现一个版本号是否是坏的版本,确保调用次数最少

被调函数要实现根据给定的版本号,找到首先是最坏的版本。最坏的版本号的特点是当前及其之后版本号都是属于坏的版本。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/57406047

46

Valid Perfect Square

Given a positive integer num, write a function which returns True if num is a perfect square else False.

Note: Do not use any built-in library function such as sqrt.

Example 1:

Input: 16

Returns: True

Example 2:

Input: 14

Returns: False

分析:给定一个正整数,判定它是否是一个完全平方数。不能使用内置的sqrt。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/59481236

47

Water and Jug Problem

You are given two jugs with capacities x and y litres. There is an infinite amount of water supply available. You need to determine whether it is possible to measure exactly z litres using these two jugs.

If z liters of water is measurable, you must have z liters of water contained within one or both buckets by the end.

Operations allowed:

Fill any of the jugs completely with water.

Empty any of the jugs.

Pour water from one jug into another till the other jug is completely full or the first jug itself is empty.

Example 1: (From the famous "Die Hard" example)

Input: x = 3, y = 5, z = 4

Output: True

Example 2:

Input: x = 2, y = 6, z = 5

Output: False

分析:此题是给定两个容量分别为x和y的杯子,问是否能够测量出容积为z的水。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/59745816

48

Guess Number Higher or Lower

We are playing the Guess Game. The game is as follows:

I pick a number from 1 to n. You have to guess which number I picked.

Every time you guess wrong, I'll tell you whether the number is higher or lower.

You call a pre-defined API guess(int num) which returns 3 possible results (-1, 1, or 0):

-1 : My number is lower

1 : My number is higher

0 : Congrats! You got it!

Example:

n = 10, I pick 6.

Return 6.

分析:实际上就是猜数字游戏。给定n,求猜别人拿的是哪个数字。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/59752076

49

如何从数组中找出满足 a+b=c+d 的两个数对

给定一个数组,找出数组中是否有两个数对(a, b)和(c, d), 使得 a+b=c+d,其中, a、b、c和d

是不同的元素。如果有多个答案,打印任意一个即可。例如给定数组:

[3, 4, 7, 10, 20, 9, 8],可以找到两个数对(3, 8)和(4, 7),使得

3+8=4+7

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/91351998

50

如何找出旋转数组的最小元素

把一个有序数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转。

输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如:

数组[3,4,5,1,2]为数组[1,2,3,4,5]的一个旋转,该数组的最小值为1。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/92384916

51

如何求数组中两个元素的最小距离

给定一个数组,数组中含有重复元素,给定两个数字num1和num2,求这两个数字在

数组中出现的位置的最小距离。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/92727422

52

如何求数组中绝对值最小的数

有1个升序排列的数组,数组中可能有正数、负数或0,求数组中元素的绝对值最小的数,

例如:数组[-10, -5, -2, 7, 15, 50],该数组中绝对值最小的数是-2。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/92801267

53

如何寻找最多的覆盖点

坐标轴上从左到右依次的点为a[0], a[1], a[2], ..., a[n-1],

设一根木棒的长度为L,求L最多能覆盖坐标轴的几个点?

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/93401148

54

如何求解迷宫问题

给定一个大小为N*N的迷宫,一只老鼠需要从迷宫的左上角(

对应矩阵的[0][0])走到迷宫的右下角(对应矩阵的[N-1][N-1]),

老鼠只能向两方向移动:向右或向下。在迷宫中,0表示没有路

(是死胡同),1表示有路。例如: 给定下面的迷宫:

1   0   0   0

1   1   0   1

0   1   0   0

1   1   1   1

途中标粗的路径就是一条合理的路径。

请给出算法来找到这么一条合理路径。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/93660114

55

如何从三个有序数组中找出它们的公共元素

给定以非递减顺序排序的三个数组,找出这三个数组中的所有公共元素。例如,

给出下面三个数组:

ar1 = [2, 5, 12, 20, 45, 85]

ar2 = [16, 19, 20, 85, 200]

ar3 = [3, 4, 15, 20, 39, 72, 85, 190]

那么这三个数组的公共元素为[20, 85]。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/93662500

56

如何判断两个字符串是否为换位字符串

换位字符串是指组成字符串的字符相同,但位置不同。例如:由于字符串"aaaabbc" 与 "abcbaaa"就是相同的字符所组的,因此它们是换位字符。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94303630

57

如何判断两个字符串的包含关系

给定由字母组成的字符串s1和s2,其中,s2中字母的个数少于s1,如何判断s1是否包含

s2? 即出现在s2中的字符在s1中都存在。

例如s1="abcdef", s2="acf",那么s1就包含s2;

如果s1="abcdef", s2="acg",那么s1就不包含s2,因为s2

中有'g',但是s1中没有'g'

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94305574

58

如何判断一个字符串是否包含重复字符

判断一个字符串是否包含重复字符。例如: 'good'就包含重复字符'0',

而'abc'就不包含重复字符

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94543155

59

如何查找到达目标词的最短链长度

给定一个词典和两个长度相同的"开始"和"目标"的单词。

找到从开始到姆博阿的最小链的长度。如果它存在,

那么这条链中的相邻单词只有一个字符不同,

而链中的每个单词都是有效单词,即它存在于词典中。

可以假设词典中存在目标字,所有词典的长度相同。

例如:

给定一个单词词典为:

[pooN, pbcc, zamc, poIc, pbca, pbIc, poIN]

start = ToolN

target = pbca

输出结果为: 7

因为: TooN(start) - pooN - poIN - poIc - pbIc - pbcc - pbca(target)。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/95906956

60

如何判断一个自然数是否是某个数的平方

设计一个算法,判断给定的一个数n是否是某个数的平方,不能使用开方运算。

例如16就满足条件,因为它是4的平方,而15则不满足条件,因为不存在

一个数使得其平方的值为15.

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/95918112

61

如何在不能使用库函数的条件下计算n的平方根

给定一个数n,求出它的平方根,比如16的平方根是4.要求不能使用库函数。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/96723712

62

黑白图像

输入一个n*n的黑白图像(1表示黑色,0表示白色),任务是统计其中八连块的个数。如果两个黑盒子有公共边或者公共顶点,就说它们属于同一个八连块。

如图所示,有3个八连块

输入:

6

100100

001010

000000

110000

111000

010100

输出:

3

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47730863

63

迷宫
一个网格迷宫由n行m列单元格组成,每个单元格要么是空地(用1表示),要么是障碍物(用0表示)。你的任务是找一条从起点到终点的最短移动序列,其中UDLR分别

表示往上、下、左、右移动到相邻单元格。任何时候都不能在障碍格中,也不能走到迷宫之外。起点和终点保证是空地。n,m<=100。

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47730893

64

迷宫路径
一个网格迷宫由n行m列单元格组成,每个单元格要么是空地(用1表示),要么是障碍物(用0表示)。你的任务是找一条从起点到终点的最短移动序列,其中UDLR分别

表示往上、下、左、右移动到相邻单元格。任何时候都不能在障碍格中,也不能走到迷宫之外。起点和终点保证是空地。n,m<=100。

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47730937

65

除法

输入正整数,按从小到大的顺序输出所有形如abcde/fghij=n的表达式,其中a~j恰好为数字0~9的一个排列,2<=n<=79.

输入:

62

输出:

79546/01283=62

94736/01528=62

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47731045

66

最大乘积

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47731081

67

分数拆分

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47731123

68

双基回文数

如果一个正整数n至少在两个不同的进位制b1和b2下都是回文数(2<=b1,b2<=10),则称n是双基回文数(注意,回文数不能包含前导0)。输入正整数S<10^6,输出比

S大的最小双基回文数>

输入:1600000(1632994)

输出:1632995

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47731141

69

倒水问题

有装满水的6升杯子、空的3升杯子和一升杯子,3个杯子中都没有刻度。在不使用其他道具的情况下,是否可以量出4升的水呢?

输入:

6(满杯水所在的刻度) 3 1

输出:

(6,0,0)->(3,3,0)->(3,2,1)->(4,2,0)

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47746957

70

八数码问题

编号为1~8的8个正方形滑块被摆成3行3列(有一个格子空留),如图所示。每次可以把与空格相邻的滑块(有公共边才算相邻)移到空格中,而它原来的位置就称为了

新的空格。给定初始局面和目标局面(用0表示空格格),你的任务是计算出最少的移动步数。如果无法达到目标局面,则输-1.

2     6     4     8  1    5

1     3     7       7  3    6

5     8     4     2

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47746983

71

八数码问题之哈希去重

输入:

2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2

输出:

31

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47746995

72

八数码问题之stl

1set<State> vis,这样只需要调用if(vis.count(s))来判断s是否在集合vis中,并用vis.insert(s)加入集合,用vis.remove(s)从集合中移除s。

问题:并不是所有类型的State都可以作为set中的元素类型。set的元素必须定义"<"运算符,C语言原生的数组(包括字符数组)却不行。

2如果数组不能转化为整数,自己声明结构体,重载函数调用符比较状态。下面中,整数a和b分别是两个状态在状态数组st中的下标,在比较时直接使用memcpy来比较整个

内存块

输入:

2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2

输出:

31

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47747019

73

二分查找

本质:有序表中使用二分查找,log2(1000)

深入:

如果数组中多个元素都是v,上面的函数返回的是中间的一个。能不能呢个求出值等于v的完整区间呢?

下面的程序当v存在时返回它出现的第一个位置。如果不存在,返回这样一个下标i:在此处插入v(原来的元素A[i],A[i+1],..全部往后移动一个位置)后序列仍然有序

思路

排序后:

0 1 3 4 6 7 9 9

输入:

8

1 9 6 3 4 7 9 0

3

8

1 9 6 3 4 7 9 0

5

输出:

2

-1

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47747225

74

二分查找之lowerBound

注意:对于二分查找的一个系列,high都是用数组长度来计算,真正是取不到的

如果数组中多个元素都是v,上面的函数返回的是中间的一个。能不能呢个求出值等于v的完整区间呢?

下面的程序当v存在时返回它出现的第一个位置。如果不存在,返回这样一个下标i:在此处插入v(原来的元素A[i],A[i+1],..全部往后移动一个位置)后序列仍然有序

输入:

8

0 1 3 4 6 7 9 9

5

8

0 1 4 4 4 4 9 9

4

输出:

4

2

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47747247

75

二分查找之upperBound

写一个upperBound程序,当v存在时返回它出现的最后一个位置的后面的一个位置。如果不存在,返回这样一个下标i:在此处插入v(原来的元素A[i],A[i+1],..全部

往后移动一个位置)后序列仍然有序。

输入:

8

0 1 3 4 6 7 9 9

5

8

0 1 3 4 4 4 9 9

4

8

0 3 3 4 4 4 9 9

3

输出:

4

6

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47747257

76

二分查找之范围统计

给出n个整数xi和m个询问,对于每个询问(a,b),输出闭区间[a,b]内的整数xi的个数。

输入:

8

0 1 3 4 6 7 9 9

3 9

输出:

6

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47747273

77

非线性方程求根

一次向银行借a元钱,分b月还清。如果需要每月还c元,月利率是多少(按复利率计算)?例如借2000元,分4个月每月还510,则月利率为0.797%。答案应不超过100%。
输入:

2000 4 510

输出:

0.797%

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47775495

78

统计书中的单词及出现次数,实现一个数据结构进行存储

编程珠玑

https://blog.csdn.net/qingyuanluofeng/article/details/54647029

参考:
[1]计算机考研--机试指南,王道论坛 组编
[2]剑指offer
[3]算法设计与分析
[4]编程之美
[5]程序员面试金典
[6]leecode
[7]Python程序员面试算法宝典
[8]刘汝佳算法竞赛入门经典
[9]算法导论
[10]编程珠玑

算法 64式 7、搜索算法整理_第2部分_16到30题相关推荐

  1. 算法 64式 7、搜索算法整理_第1部分_1到15题

    1 算法思想 算法分类 搜索算法主要分为: 暴力搜索+剪枝,枚举,广度优先搜索,深度优先搜索,二分查找,哈希查找, A*算法,两边向中间逼近,从中间向两边扩散等 1.1枚举 枚举: 最直白的搜索方式, ...

  2. 算法 64式 7、搜索算法整理_第4部分_46到60题

    1 算法思想 算法分类 搜索算法主要分为: 暴力搜索+剪枝,枚举,广度优先搜索,深度优先搜索,二分查找,哈希查找, A*算法,两边向中间逼近,从中间向两边扩散等 1.1枚举 枚举: 最直白的搜索方式, ...

  3. 算法 64式 7、搜索算法整理_第3部分_31到45题

    1 算法思想 算法分类 搜索算法主要分为: 暴力搜索+剪枝,枚举,广度优先搜索,深度优先搜索,二分查找,哈希查找, A*算法,两边向中间逼近,从中间向两边扩散等 1.1枚举 枚举: 最直白的搜索方式, ...

  4. 算法 64式 8、动态规划算法整理_第1部分_1到15题

    1 算法思想 动态规划 1.1含义 把问题分解成多阶段或多个子问题,顺序求解各个子问题,最后一个子问题就是初始问题的解. 概念 阶段: 问题分成的顺序的几个环节.例如最长递增子序列中每个字符就是一个阶 ...

  5. 算法 64式 8、动态规划算法整理

    1 算法思想 动态规划 1.1含义 把问题分解成多阶段或多个子问题,顺序求解各个子问题,最后一个子问题就是初始问题的解. 概念 阶段: 问题分成的顺序的几个环节.例如最长递增子序列中每个字符就是一个阶 ...

  6. 算法 64式 19、数学算法整理

    1 算法思想 2 数学系列 类别-编号 题目 遁去的一 1 特殊乘法 写个算法,对2个小于1000000000的输入,求结果. 特殊乘法举例: 123 * 45 = 1*4 + 1*5 + 2*4 + ...

  7. 算法 64式 4、回溯算法整理__第1部分_1到13题

    1算法思想 回溯 1.1含义 以深度优先方式搜索问题解的算法称为回溯法. 1.2思想 按照深度优先搜索策略,从根节点出发搜索解空间树,如果某结点不包含问题解,则逐层向祖先结点回溯:否则进入子树. 1. ...

  8. 算法 64式 17、排列组合算法整理

    1算法思想 排列组合 1.1含义 排列: 含义:从元素列表中取出指定个数的元素进行排序 公式:从n个不同元素中取出m个元素的排列个数=n!/(n-m)! 组合: 含义:从元素列表中取出指定个数的元素, ...

  9. 算法 64式 14、排序算法整理_1_1到15题

    1 算法思想 这里将寻找最小/大的前k个数,寻找逆序对,线性时间选择(寻找第k小/大的元素),奇偶/大小写字符分别放在前后部分等和排序相关类型的题目,放在了排序而不是查找中. 1.1含义 排序含义:重 ...

最新文章

  1. 浅谈数据结构-平衡二叉树
  2. HTML中INPUT type=date标签如何赋值注意问题
  3. Java命令行界面(第6部分):JOpt简单
  4. 奥特曼传奇英雄存档丢了怎么找回_热血传奇:道士最帅武器—玄天
  5. 微信中音乐播放在ios不能自动播放解决
  6. HDU 1867 KMP
  7. Pairs Forming LCM(素因子分解)
  8. java时间格式24小时制12小时制
  9. GPGGA \ GPRMC 格式解析
  10. TCP 和 UDP 的区别 TCP 和 UDP 详解
  11. 基于JAVA幼儿园管理系统计算机毕业设计源码+系统+lw文档+部署
  12. c语言谱曲软件,基于C语言的音乐谱曲技巧与应用研究
  13. 华尔街最闪耀的新星:量子计算
  14. CentOS7.X安装部署Glassfish4.1.2
  15. python爬虫的意义_爬虫的意义与爬虫基本流程
  16. 后台和用户跟踪要点_联系人跟踪应用程序的一些基本要点
  17. 什么是运维?运维工程师主要是做什么?
  18. E - EXCEL排序
  19. 心电 基线漂移的处理研究论文
  20. TTS什么意思,缩写,微软TTS语音引擎(中文)5.1 “TTS”是“文本到语音(Text To Sound)”的简称

热门文章

  1. 也谈时间管理和GTD
  2. 非静压模型NHWAVE学习(7)——波浪变形模拟算例学习(Wave transformation over an elliptical shoal)
  3. 获取office版本
  4. 最短路算法 :Bellman-ford算法 Dijkstra算法 floyd算法 SPFA算法 详解
  5. 祛除装修异味的方法 总有一种适合你!
  6. .globl expression
  7. 放弃win10自带OneNote之后,下载完整版OneNote2016
  8. [原]OpenGL基础教程(二)多边形绘制
  9. Deep Learning之手写数字识别
  10. 程序员兼职接私活平台大全,兼职也能月薪上万