剑指Offer错题总结

数值的整数次方

题目描述:

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

保证base和exponent不同时为0

class Solution {
public:
    double quickMulti(double base, int exponent)
    {
        if(exponent == 1)
            return base;
        if(exponent == 0)
            return 1.0;
        double ret = quickMulti(base, exponent / 2);
        if(exponent & 0x1)
        {
            return ret * ret * base;
        }
        else
            return ret * ret;
    }
    double Power(double base, int exponent) {
    	if(exponent < 0)
        {
            base = 1.0 / base;
            exponent *= -1;
        }
        return quickMulti(base, exponent);
    }
};

二叉搜索树与双向链表

题目描述:

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

class Solution {
public:
    TreeNode* dfs(TreeNode* root, TreeNode* head, TreeNode* cur)
    {
    	if(!root)
            return nullptr;
        dfs(root->left, head, cur);
        if(!head)
        {
       		head = root;
        }
        else
        {
            cur->right = root;
            root->left = cur;
        }
        cur = root;
        dfs(root->right, head, cur);
        return head;
    }
    TreeNode* Convert(TreeNode* pRootOfTree) {
		if(!pRootOfTree)
            return nullptr;
        TreeNode* head = nullptr;
        TreeNode* cur = nullptr;
        dfs(pRootOfTree, head, cur);
       	return head;
    }
};

字符串的排列

题目描述:

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

输入描述:

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

class Solution{
public:
    void dfs(string str, int pos, set<string>& st)
    {
		if(pos + 1 == str.size())
        {
			st.insert(str);
            return;
        }
        for(int i = pos; i < st.size(); i++)
        {
      		swap(str[i], str[pos]);
            dfs(str, pos+1, st);
            swap(str[i], str[pos]);
        }
        return;
    }
	vector<string> Permutation(string str)
    {
  		if(str.empty())
            return vector<string>();
        set<string> st;
        dfs(str, 0, st);
        return vector<string>(st.begin(), st.end());
    }
};

两个链表的第一个公共结点

题目描述

输入两个链表,找出它们的第一个公共节点。

class Solution{
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB){
        if(!headA || !headB)
            return nullptr;
        ListNode* p1 = headA;
        ListNode* p2 = headB;
        while(p1 != p2)
        {
			p1 = p1 ? p1->next:headB;
            p2 = p2 ? p2->next:headA;
        }
        return p1;
    }
};

最小的K个数

题目描述:

给定一个数组,找出其中最小的K个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。如果K>数组的长度,那么返回一个空的数组。

//大顶堆方法
class Solution
{
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
    {
		if(input.empty() || k > input.size() || k == 0)
            return vector<int>();
        if(k == input.size())
            return input;
        priority_queue<int, vector<int>> pq;
        for(int i = 0; i < input.size(); i++)
        {
			if(i < k)
            {
				pq.push(input[i]);
            }
            else
            {
                if(input[i] < pq.top())
                {
                    pq.pop();
                    pq.push(input[i]);
                }
            }
        }
        vector<int> ans;
        while(!pq.empty())
        {
            ans.push_back(pq.top());
            pq.pop();
        }
        return ans;
    }
};
//快速排序+二分法
class Solution{
public:
    int quickSort(vector<int>& input, int left, int right)
    {
        if(left < right)
        {
            while(left < right)
            {
                int x = input[left];
                while(left < right && input[right] >= x)
                    right--;
                if(left < right)
                    std::swap(input[left++],input[right]);
                while(left < right && input[left] < x)
                    left++;
                if(left < right)
                    std::swap(input[left], input[right--]);
            }
            input[left] = x;
            return left;
        }
        return left;
    }
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k){
        if(input.empty() || k > input.size() || k == 0)
            return vector<int>();
        if(k == input.size())
            return input;
        int left = 0;
        int right = input.size() - 1;
        while(left < right)
        {
            int p = quickSort(input, left, right);
            if(p+1 == k)
                return vector<int>(input.begin(), input.begin() + k);
            if(p+1 < k)
                left = p+1;
            else
                right = p;
        }
        return vector<int>();
    }
};

把数组排成最小的数

题目描述:

输入一个正整数数组,把数组里的所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

class Solution{
public:
    string PrintMinNumber(vector<int> numbers){
        vector<string> temp;
        for(int i = 0; i < numbers.size(); i++)
            temp.push_back(to_string(numbers[i]));
        sort(temp.begin(), temp.end(), [](string a,string b){ return a+b<b+a; });
        string ans;
        for(int i = 0;i<numbers.size();i++)
            ans += temp[i];
        return ans;
    }
}

数组的逆序对

题目描述:

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。即输出P%1000000007。

输入
[1,2,3,4,5,6,7,0]
输出
7
//归并排序
class Solution {
    const int flag = 1000000007;
public:
    void merge(vector<int>& data, int left, int mid, int right, int& ans)
    {
        vector<int> temp(right-left+1);
        int i = left, j = mid+1;
        int k = 0;
        while(i <= mid && j <= right)
        {
            if(data[i] < data[j])
                temp[k++] = data[i++];
            else{
                temp[k++] = data[j++];
                ans += (mid - i + 1);
                ans = ans % flag;
            }
        }
        while(i <= mid)
        {
            temp[k++] = data[i++];
        }
        while(j <= right)
        {
            temp[k++] = data[j++];
        }
        for(int i = left, j = 0; j < k; j++, i++)
        {
            data[i] = temp[j];
        }
        return;
    }
    void mergeSort(vector<int>& data, int left, int right, int& ans)
    {
        if(left >= right)
            return;
        int mid = left + (right - left) / 2;
        mergeSort(data, left, mid, ans);
        mergeSort(data, mid+1, right, ans);
        merge(data, left, mid, right, ans);
        return;
    }
    int InversePairs(vector<int> data) {
        if(data.empty())
            return 0;
        int ans = 0;
        mergeSort(data, 0, data.size() - 1,  ans);
        return ans;
    }
};

丑数

//包含质因子2,3,5的数称为丑数
//所以任何数乘以2,3,5的结果都是丑数
//第一个丑数是1,要求第index个
//所以就从1开始一直乘2,3,5,然后排序求出第index个数即可
//因为每次的乘积大小都不同,所以用三个变量分别标记每次乘积最小的那个
class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        if(index <= 0)
            return 0;
        vector<int> dp(index);
        int a = 0;
        int b = 0;
        int c = 0;
        dp[0] = 1;
        for(int i = 1; i < index; i++)
        {
            int n1 = dp[a] * 2;
            int n2 = dp[b] * 3;
            int n3 = dp[c] * 5;
            dp[i] = min(min(n1, n2), n3);
            if(dp[i] == n1)
                a++;
            if(dp[i] == n2)
                b++;
            if(dp[i] == n3)
                c++;
        }
        return dp[index-1];
    }
};

孩子们的游戏

//用temp记录下一次开始的位置
//(m-1)%n是前进的位置
//加上(temp)%n是该开始的位置
class Solution {
public:
    int LastRemaining_Solution(int n, int m) {
        if(m <= 0 || n <= 0)
            return -1;
        int temp = 0;
        vector<int> vc;
        for(int i = 0; i < n; i++)
            vc.push_back(i);
        while(n > 1)
        {
            temp = (temp + m - 1) % n;
            auto be = vc.begin();
            std::advance(be, temp);
            vc.erase(be);
            n--;
        }
        return vc[0];
    }
};

把字符串转换成整数

class Solution {
public:
    int StrToInt(string str) {
        int len = str.size();
        if(len == 0)
            return 0;
        int index = 0;
        if(!isdigit(str[index]) && str[index] != '+' && str[index] != '-')
            return 0;
        long long ans = 0;
        bool neg = str[index] == '-' ? true : false;
        index = isdigit(str[index]) ? index : index+1;
        while(index < len && isdigit(str[index]))
        {
            ans = ans * 10 + (str[index++] - '0');
            if(!neg && ans >= INT_MAX)
            {
                ans = INT_MAX;
                break;
            }
            else if(neg && ans >= INT_MAX + 1L)
            {
                ans = INT_MAX + 1L;
                break;
            }
        }
        if(index != len)
            return 0;
        return !neg ? static_cast<int>(ans) : static_cast<int>(-ans);
    }
};

链表中环的入口节点

class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        if(!pHead)
            return nullptr;
        ListNode* fast = pHead;
        ListNode* slow = pHead;
        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
            if(slow == fast)
                break;
        }
        if(!fast || !fast->next)
            return nullptr;
        fast = pHead;
        while(fast != slow)
        {
            fast = fast->next;
            slow = slow->next;
        }
        return fast;
    }
};

构建乘积数组

//首先从左往右计算
//B[i]一开始表示在i位置左边(不包括i位置)的乘积
//然后从右往左计算
//B[i]表示在i位置右边(不包括i位置)的乘积
class Solution {
public:
    vector<int> multiply(const vector<int>& A) {
        vector<int> B(A.size(), 1);
        for(int i = 1; i < A.size(); i++)
        {
            B[i] = A[i-1] * B[i-1];
        }
        int temp = 1;
        for(int i = A.size() - 2; i >= 0; i--)
        {
            temp = temp * A[i+1];
            B[i] = B[i] * temp;
        }
        return B;
    }
};

滑动窗口的最大值

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size) {
        if(size > num.size())
            return vector<int>();
        vector<int> ans;
        deque<int> dq;
        for(int i = 0; i < num.size(); i++)
        {
            while(!dq.empty() && num[i] > num[dq.back()])
                dq.pop_back();
            dq.push_back(i);
            if(!dq.empty() && i - dq.front() > size -1)
                dq.pop_front();
            if(i >= size - 1)
                ans.push_back(num[dq.front()]);
        }
        return ans;
    }
};

剪绳子

class Solution {
public:
    int cutRope(int number, vector<int>& mark)
    {
        if(number <= 4)
            return number;
        if(mark[number] != -1)
            return mark[number];
        int ret = 0;
        for(int i = 1; i < number; i++)
        {
            ret = max(ret, i * cutRope(number-i, mark));
        }
        mark[number] = ret;
        return ret;
    }
    int cutRope(int number) {
        if(number == 2)
            return 1;
        if(number == 3)
            return 2;
        if(number == 4)
            return 4;
        vector<int> mark(number+1, -1);
        return cutRope(number, mark);
    }
};

正则表达式匹配

class Solution {
public:
    bool match(string str, string pattern) {
        // write code here
        if(pattern.empty())
            return str.empty();
        int row = str.size();
        int col = pattern.size();
        vector<vector<int>> dp(row+1, vector<int>(col+1, false));
        dp[0][0] = true;
        for(int i = 2; i <= col; i++)
            if(pattern[i-1] == '*')
                dp[0][i] = dp[0][i-2];
        
        for(int i = 1; i <= row; i++)
        {
            for(int j = 1; j <= col; j++)
            {
                if(str[i-1] == pattern[j-1] || pattern[j-1] == '.')
                    dp[i][j] = dp[i-1][j-1];
                else if(pattern[j-1] == '*' && j >= 2)
                {
                    if(pattern[j-2] != str[i-1] && pattern[j-2] != '.')
                        dp[i][j] = dp[i][j-2];
                    else
                    {
                        dp[i][j] = dp[i][j-2] || dp[i-1][j];
                    }
                }
            }
        }
        return dp[row][col];
    }
};

序列化二叉树

//层次遍历
//atoi()函数的参数是const char*,对于一个字符串必须用c_str()函数把string转换成const char*
//
class Solution {
public:
    char* Serialize(TreeNode *root) {    
        string str;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            TreeNode* temp = q.front();
            q.pop();
            if(!temp)
            {
                str += '#';
                str += ',';
            }
            else
            {
                str += to_string(temp->val);
                str += ',';
                q.push(temp->left);
                q.push(temp->right);
            }
        }
        char* ch = new char[str.size() + 1];
        strcpy(ch, str.c_str());
        return ch;
    }
    TreeNode* Deserialize(char *str) {
        if(!str)
            return nullptr;
        string str1(str);
        if(str1[0] == '#')
            return nullptr;
        TreeNode* root = new TreeNode(atoi(str1.c_str()));
        queue<TreeNode*> q;
        q.push(root);
        str1 = str1.substr(str1.find_first_of(',') + 1);
        while(!q.empty() && !str1.empty())
        {
            TreeNode* temp = q.front();
            q.pop();
            if(str1[0] == '#')
            {
                temp->left = nullptr;
                str1 = str1.substr(2);
            }
            else
            {
                temp->left = new TreeNode(atoi(str1.c_str()));
                str1 = str1.substr(str1.find_first_of(',') + 1);
                q.push(temp->left);
            }
            if(str1[0] == '#')
            {
                temp->right = nullptr;
                str1 = str1.substr(2);
            }
            else
            {
                temp->right = new TreeNode(atoi(str1.c_str()));
                str1 = str1.substr(str1.find_first_of(',') + 1);
                q.push(temp->right);
            }
        }
        return root;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值