剑指offer刷题(二)

1.

题目描述

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy

时间复杂度O(n) 思路:计算出字符串的长度,以及新字符串的长度(原长度+2*空格数),两个指针,一个指向新字符串结尾,一个指向原字符串结尾,从后到前赋值字符串,由于新字符串尾指针大于原字符串尾指针,所以不会产生覆盖,减少移动次数,从而提高效率。

class Solution {
public:
	void replaceSpace(char *str,int length) {
            if(str == NULL || length <= 0)
                return;
        /*计算空格的个数*/
        int originalLength = 0;
        int numberOfBlack = 0;
        int i = 0;
        while(str[i] != '\0'){
            ++originalLength;
            if(str[i] == ' ')
                ++numberOfBlack;
            i++;
        }
        //新字符串的长度=originalLength+2*numberOfBlack
        int newLength = originalLength + 2 * numberOfBlack;
        int indexNew = newLength;
        int indexOld = originalLength;
        while(indexOld >= 0 && indexNew >indexOld){
            if(str[indexOld] == ' '){
                str[indexNew--] = '0';
                str[indexNew--] = '2';
                str[indexNew--] = '%';               
            }
            else
                str[indexNew--]=str[indexOld];    
            --indexOld;
        }   

	}
};

2.输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

思路:节点入栈,反转

vectornode;    node.push_back(); node.empty()

std::stack a; a.push() a.pop()  a.empty()

*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector printListFromTailToHead(ListNode* head) {
        vector  a;
        
        if(head == NULL)
            return a;
            std::stack node;     
            ListNode *pNode = head;
            while(pNode != NULL){
                node.push(pNode);
                pNode = pNode -> next;
            }
            while(!node.empty()){
                pNode = node.top();
                a.push_back(pNode -> val);
                node.pop();
            }
          return a;  
        
         
    }
};

3.输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

TreeNode* T = new TreeNode(pre[0]);

vector 数组长度.size()  添加元素.push_back()

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector pre,vector vin) {
       
        if(pre.size() == 0 || vin.size() == 0)
            return NULL;
        TreeNode* T = new TreeNode(pre[0]);
        int indexRoot = 0;
        for(int i = 0;i < vin.size();i++){
            if(vin[i] == pre[0]){
                indexRoot = i;
                break;
            }
        }
        vector pre_left,pre_right,vin_left,vin_right;
        for(int j = 0;j < indexRoot;j++){
            pre_left.push_back(pre[j + 1]);
            vin_left.push_back(vin[j]);
        }
        for(int k = 0;k < pre.size()-indexRoot-1;k++){
            pre_right.push_back(pre[k + indexRoot + 1]);
            vin_right.push_back(vin[k + indexRoot + 1]);          
        }        
       
        T->left = reConstructBinaryTree(pre_left,vin_left);
        T->right = reConstructBinaryTree(pre_right,vin_right);
        return T;
        
        }
};

4.输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

A->B->C->D->E

先将其复制为A->A'->B->B'->C->C'->D->D'->E->E'

修改复制出来的结点的random指针:p->next->random = p->random->next;

提取出偶数位置的结点,连成链表:A'->B'->C'->D'......

注意:链表只有一个节点的情况以及在遍历链表的过程中考虑当前只有一个结点的情况

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead){
       
        if(pHead == NULL){
            return NULL;
            
        }
         RandomListNode *cur = pHead;
            
        //在原链表各节点后创建副本
        while(cur){
            RandomListNode * newnode = new RandomListNode(cur->label);       
            newnode->next = cur->next;           
            cur->next = newnode;           
            cur = newnode->next;  
        }
        //复制random指针,A的random的next恰好为A'的random
        cur = pHead;
        
        while(cur){        
            if(cur->random != NULL){
                cur->next->random = cur->random->next;               
            }else{
                cur->next->random = NULL;
            }         
            cur = cur->next->next;
        }
        //取偶数节点
        cur = pHead;
        RandomListNode * newList = cur->next;
        RandomListNode * newListNode = newList;
        while(cur){
            //先将原链表指针移动
            cur->next = newListNode->next;  
            cur = cur->next;
            
            if(cur != NULL){//有超过一个节点
                newListNode->next = cur->next;  
                newListNode = newListNode->next;
            }
                
        }
        return newList;  
    }
    
};

5.输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

思路:二叉搜索树本身为左子树<根<右子树,中序遍历递归

辅助结点:链表的头结点、尾结点(尾插加入新结点)

左子树转换为链表

根:根节点连接在当前链表上:(根节点的left为尾指针,尾指针的right为根节点,尾指针后移)

右子树转换为链表

 

class Solution {
    TreeNode* ListHead = NULL;
    TreeNode* ListTail = NULL;
    //ListHead保存链表的头结点,tail当前的结点的前一个
public:
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        if(!pRootOfTree){
            return NULL;            
        }
        Convert(pRootOfTree->left);
        if(ListHead == NULL){
            ListHead = pRootOfTree;
            ListTail = pRootOfTree;
        }else{
            //修改即将连上结点的前驱:left,为当前链表的尾结点
            //修改尾结点的后继为根结点,
            //修改尾指针
            pRootOfTree->left = ListTail;
            ListTail->right = pRootOfTree;
            ListTail = pRootOfTree;
            
        }
      Convert(pRootOfTree->right);       
      return ListHead;      
    }
};

6:题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。


class Solution {
public:
    vector Vec;
    void Permutation(string s,unsigned int pbegin)
    {
        if(pbegin==s.size()-1)
            Vec.push_back(s);
        else
        {
        for(unsigned int i=pbegin;i<=s.size()-1;++i)
        {
            if(i!=pbegin&&(s[i]==s[pbegin]||s[i]==s[i-1]))
                continue;
            char temp;
            temp = s[pbegin];
            s[pbegin]=s[i];
            s[i]=temp;
             //swap(s[pbegin],s[i]);
             Permutation(s,pbegin+1);
             //swap(s[pbegin],s[i]);
            temp = s[pbegin];
            s[pbegin]=s[i];
            s[i]=temp;
        }
        }
    }
    vector Permutation(string str) {
        if(str.size()<=0)
            return{};
        Permutation(str,0);
        sort(Vec.begin(),Vec.end());   //那字典序排序
        return Vec;
    }
};

7.数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

思路:做法特别传统,用了两个指针,一个从前走,一个从尾部遍历(子循环对从前走的指针所指元素计数),

class Solution {
public:
    int MoreThanHalfNum_Solution(vector numbers) {
       if(numbers.empty()){
           return 0;
       }
        int len = numbers.size();
        int count = 0; 
        for(int i = 0;i < len;i++){
            int j = len-1;
            count++;//对number[i]计数
            while(j>=i){
                if(i == j && count > len / 2){
                    return numbers[i];                    
                }else{
                    if(numbers[i]==numbers[j]){
                        count++;
                    }
                    j--;   //居然手滑写成了j++                                  
                }
            } 
            count = 0;//一个元素判断完了,count置0,对下一个计数
        }
        return 0;       
    }
};

 

你可能感兴趣的:(数据结构与算法)