目录
面试题38:字符串的排列(书上解法暂未调试通过)
例1:找出所有被X包围的区域,并将其中的‘O’全部替换为‘X’.(自己编写的代码暂未调试通过)
1.剑指Offer
面试题36:二叉搜索树与双向链表
题目描述:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路:中序遍历+递归实现
书上解法:
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
TreeNode* pLastNodeinList=nullptr;
ConvertNode(pRootOfTree,&pLastNodeinList);
TreeNode* pHeadofList=pLastNodeinList;
while(pHeadofList!=nullptr&&pHeadofList->left!=nullptr){
pHeadofList=pHeadofList->left;
}
return pHeadofList;
}
void ConvertNode(TreeNode* pRootOfTree,TreeNode** pLastNodeinList){
if(pRootOfTree==nullptr){
return;
}
TreeNode* pCurrent=pRootOfTree;
if(pCurrent->left){
ConvertNode(pCurrent->left,pLastNodeinList);
}
pCurrent->left=*pLastNodeinList;
if(*pLastNodeinList){
(*pLastNodeinList)->right=pCurrent;
}
pCurrent=*pLastNodeinList;
if(pCurrent->right){
ConvertNode(pCurrent->right,pLastNodeinList);
}
}
};
牛客网调试出现数组和指针越界问题,暂时没有想出解决方案,后面在修改。
正确代码:(已调试通过!)
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(pRootOfTree==nullptr) return nullptr;
TreeNode* pre=nullptr;
ConvertNode(pRootOfTree,pre);
TreeNode* pHead=pRootOfTree;
while(pHead->left){
pHead=pHead->left;
}
return pHead;
}
void ConvertNode(TreeNode* cur,TreeNode*& pre){
if(cur==nullptr) return;
ConvertNode(cur->left,pre);
cur->left=pre;
if(pre){
pre->right=cur;
}
pre=cur;
ConvertNode(cur->right,pre);
}
};
面试题38:字符串的排列
题目描述:
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
思路:递归法,问题转换为先固定第一个字符,求剩余字符的排列;求剩余字符排列时跟原问题一样。
(1) 遍历出所有可能出现在第一个位置的字符(即:依次将第一个字符同后面所有字符交换);
(2) 固定第一个字符,求后面字符的排列(即:在第1步的遍历过程中,插入递归进行实现)。
需要注意的几点:
(1) 先确定递归结束的条件,例如本题中可设begin == str.size() - 1;
(2) 形如 aba 或 aa 等特殊测试用例的情况,vector在进行push_back时是不考虑重复情况的,需要自行控制;
(3) 输出的排列可能不是按字典顺序排列的,可能导致无法完全通过测试用例,考虑输出前排序,或者递归之后取消复位操作。
代码:
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> result;
if(str.empty()) return result;
permutation(str,result,0);
sort(result.begin(),result.end()); //生成的数组可能不是字典序,单独对其进行排序
return result;
}
void permutation(string str,vector<string> &result, int begin){
if(begin == str.size()-1){ //递归的结束条件,
if(find(result.begin(),result.end(),str)==result.end()){
result.push_back(str); //如果result中不存在str才添加,避免aa和aa这样的重复情况。
}
}
else{
for(int i=begin;i<str.size();i++){
swap(str[i],str[begin]);
permutation(str,result,begin+1);
swap(str[i],str[begin]);
}
}
}
void swap(char &first,char &second){
char temp=first;
first=second;
second=temp;
}
};
2.Leetcode
例1:找出所有被X包围的区域,并将其中的‘O’全部替换为‘X’.
Given a 2D board containing'X'and'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
思路:首先将边界上的O以及与边界O相连的O都标记为N,然后将其他的O都变为X,最后将N重新变为O即可,采用深度优先遍历。
代码:(已调试通过!)
class Solution {
public:
void solve(vector<vector<char>> &board) {
if (board.empty() || board.size()== 0 || board[0].size() == 0) {
return;
}
int row = board.size();
int column = board[0].size();
for (int i = 0; i < row; i++) {
dfs(board, i, 0);
dfs(board, i, column - 1);
}
for (int i = 0; i < column; i++) {
dfs(board, 0, i);
dfs(board, row - 1, i);
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if(board[i][j]=='O'){
board[i][j]='X';
}
if(board[i][j]=='N'){//把标记为N的重新变为O
board[i][j]='O';
}
}
}
}
// 将边界上的O变为N,与边界O相连的所有O都变为N,N是一个标记表示不可变的O
void dfs(vector<vector<char>> &board, int i, int j) {
int row = board.size();
int column = board[0].size();
if (i < 0 || i >= row || j < 0 || j >= column) {
return;
}
if (board[i][j] == 'X') {
return;
}
if (board[i][j] == 'O') {
board[i][j] = 'N';
dfs(board, i + 1, j);
dfs(board, i - 1, j);
dfs(board, i, j + 1);
dfs(board, i, j - 1);
}
}
};
错误代码:出现如下错误,明明和上面代码完全一样就是无法调试通过,很郁闷,暂留问题!!!!
不通过
您的代码已保存
内存超限:您的程序使用了超过限制的内存
case通过率为0.00%
class Solution {
public:
void solve(vector<vector<char>> &board) {
if(board.empty()|| board.size()==0|| board[0].size()==0){
return;
}
int row=board.size();
int column=board[0].size();
for(int i=0;i<row;i++){
dfs(board,i,0);
dfs(board,i,column-1);
}
for(int i=0;i<column;i++){
dfs(board,0,i);
dfs(board,row-1,i);
}
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
if(board[i][j]=='O'){
board[i][j]='X';
}
if(board[i][j]=='N'){
board[i][j]='O';
}
}
}
}
void dfs(vector<vector<char>> &board,int i,int j){
int row=board.size();
int column=board[0].size();
if(i<0||i>=row||j<0||j>=column){
return;
}
if(board[i][j]=='X'){
return;
}
if(board[i][j]=='O'){
board[i][j]=='N';
dfs(board,i+1,j);
dfs(board,i-1,j);
dfs(board,i,j+1);
dfs(board,i,j-1);
}
}
};
例2:合并两个已排序的数组到其中一个已排序的数组中
题目描述:
Given two sorted integer arrays A and B, merge B into A as one sorted array.
Note:
You may assume that A has enough space to hold additional elements from B. The number of elements initialized in A and B are m and n respectively.
思路:从后往前依次比较后插入数组元素。
i从A的末尾,j从B末尾开始,两两比较,大的放在末端。
比如A[4,5,7] B[1,2,6],。
7比6大,A[5]处放置7,然后i前移。
再次比较5 和6,6放在A[4]处。
如此类推如果A穷尽,把B元素依次放进A的前几个位置,如果B穷尽,正好结束。
代码:
class Solution {
public:
void merge(int A[], int m, int B[], int n) {
if(m==0){
for(int i=0;i<n;i++){
A[i]=B[i];
}
}
else{
int i=m-1;
int j=n-1;
int k=m+n-1;
while(i>=0&&j>=0){
if(A[i]>B[j]){
A[k--]=A[i--];
}
else{
A[k--]=B[j--];
}
}
if(i==-1){
for(;j>=0;j--){
A[j]=B[j];
}
}
}
}
};