编程之旅-Day11

这篇博客讲述了编程学习的两个挑战:如何将二叉搜索树转换为排序的双向链表,以及如何找到字符串的所有字典序排列。对于二叉搜索树,博主分享了中序遍历和递归实现的思路,同时提到在调试过程中遇到的问题。在字符串排列部分,博主使用递归方法解决,并提出了需要注意的细节。此外,还讨论了LeetCode上的两个问题,包括寻找被X包围的区域和合并两个已排序数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

Day11-学习内容

1.剑指Offer

面试题36:二叉搜索树与双向链表

面试题38:字符串的排列(书上解法暂未调试通过)

2.Leetcode

例1:找出所有被X包围的区域,并将其中的‘O’全部替换为‘X’.(自己编写的代码暂未调试通过)

例2:合并两个已排序的数组到其中一个已排序的数组中


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];
                }
            }
        }
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值