leetcode解题思路分析(三十二)228—234题

  1. 汇总区间
    给定一个无重复元素的有序整数数组,返回数组区间范围的汇总。

很简单的一道题,遍历一遍即可

class Solution {
    
    
public:
    vector<string> summaryRanges(vector<int>& nums) 
    {
    
    
        vector<string> ans;

        for (int i = 0; i < nums.size(); i++)
        {
    
    
            string str = to_string(nums[i]);
            int pos = i;

            while (i < nums.size() - 1 && nums[i] + 1 == nums[i + 1]) 
            {
    
    
                i++; //数字连续
            }

            if (pos != i) //若有增加
            {
    
    
                str += "->" + to_string(nums[i]);
            }

            ans.push_back(str);
        }
        return ans;
    }
};


  1. 求众数2
    给定一个大小为 n 的数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。

采用摩尔投票可解,如果直接用一个映射数组则空间复杂度不满足要求

/*
时间复杂度为:O(n)
空间复杂度为:O(1)
*/
class Solution {
    
    
public:
    vector<int> majorityElement(vector<int>& nums) {
    
    
        int len = nums.size();
        vector<int>res, cands, cnts;
        if(len == 0){
    
    //没有元素,直接返回空数组
            return res;
        }
        cands.assign(2, nums[0]);
        cnts.assign(2, 0);
        //第1阶段 成对抵销
        for(auto num: nums){
    
    
            bool flag = false;
            for(int i = 0; i < cands.size(); ++i){
    
    
                if(num == cands[i]){
    
    
                    ++cnts[i];
                    flag = true;
                    break;
                }
            }
            if(!flag){
    
    
                bool flag2 = false;
                for(int j = 0; j < cands.size(); ++j){
    
    
                    if(cnts[j] == 0){
    
    
                        flag2 = true;
                        cands[j] = num;
                        cnts[j]++;
                    }
                }
                if(!flag2){
    
    
                    for(int j = 0; j < cnts.size(); ++j){
    
    
                        --cnts[j];
                    }
                }
            }
        }

        //第2阶段 计数 数目要超过三分之一
        cnts[0] = cnts[1] = 0;
        if(cands[0] == cands[1])
            cands.pop_back();
        for(auto num:nums){
    
    
            for(int i = 0; i < cands.size(); ++i){
    
    
                if(cands[i] == num){
    
    
                    ++cnts[i];
                    break;
                }
            }
        }
        for(int i = 0; i < cands.size(); ++i){
    
    
            if(cnts[i] > len / 3){
    
    
                res.push_back(cands[i]);
            }
        }
        return res;
    }
};

  1. 二叉搜索树第K小元素
    给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素

最简单的做法就是用递归或者迭代去排列中序遍历,取第k个元素即可。其中迭代比起递归更优,因为迭代找到第k个可以立马停止返回。


class Solution {
    
    

    int m_cnt = 0, m_ret = 0;

public:
    int kthSmallest(TreeNode* root, int k) 
    {
    
    
        __midOrder(root, k);
        return m_ret;
    }

private:
    void __midOrder(TreeNode *root, int k)
    {
    
    
        if (root == NULL) return;

        __midOrder(root->left, k);
        m_cnt++;
        if (m_cnt == k) m_ret = root->val;
        __midOrder(root->right, k);
    }
};

class Solution {
    
    

    int m_cnt = 0, m_ret = 0;

public:
    int kthSmallest(TreeNode* root, int k) 
    {
    
          
        return __midOrder(root, k);
    }

private:
    int __midOrder(TreeNode *root, int k)
    {
    
    
        stack<TreeNode *> s;
        TreeNode *cur = root;
        while (s.size() || cur)
        {
    
    
            while (cur)
            {
    
    
                s.push(cur);
                cur = cur->left;
            }
            cur = s.top();
            s.pop();
            m_cnt++;
            if (m_cnt == k) return cur->val;
            cur = cur->right;
        }
        return 0;
    }
};
  1. 2的幂
    很简答的一道题
class Solution {
    
    
public:
    bool isPowerOfTwo(int n) {
    
    
        if (n <= 0) return false;
        while (n > 1)
        {
    
    
            if (n % 2 != 0)
                return false;
            else 
                n = n / 2;
        }
        return true;
    }
};
  1. 用栈实现队列

和之前的队列一样,只需要多一个栈即可实现

class MyQueue {
    
    
public:
    stack<int> inStack;
    stack<int> outStack;
    
    MyQueue() {
    
    

    }
    
    void push(int x) {
    
    
        inStack.push(x);
    }
    
    int pop() {
    
    
        cheak();
        int a=outStack.top();
        outStack.pop();
        return a;
    }

    int peek() {
    
    
        cheak();
        return outStack.top();
    }
    

    bool empty() {
    
    
        return inStack.empty()&&outStack.empty();
    }

    void cheak()
    {
    
    
        if(outStack.empty())
        {
    
    
            while(!inStack.empty())
            {
    
    
                outStack.push(inStack.top());
                inStack.pop();
            }

        }
    }
};

/*
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */
  1. 数字1的个数
    给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。
    将 i 从 1 遍历到 n,每次遍历 i 扩大 10 倍:
    (n/(i*10))∗i表示 (i*10)位上1的个数。
    min(max((n mod (i*10)} )-i+1, 0), i)})表示需要额外数的(i*10)位上1的个数。
class Solution {
    
    
public:
int countDigitOne(int n)
{
    
    
    int countr = 0;
    for (long long i = 1; i <= n; i *= 10) {
    
    
        long long divider = i * 10;
        countr += (n / divider) * i + min(max(n % divider - i + 1, 0LL), i);
    }
    return countr;
}
};

  1. 回文链表
    请判断一个链表是否为回文链表。你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

空间复杂度O(1)表明不能用栈存储或者递归查找,因此这里的做法是,先用快慢指针获得中间节点,在快慢指针移动过程中反转前面一半,然后再比较后一半和前一半的值是否相等。注意中间节点奇偶情况判断

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    bool isPalindrome(ListNode* head) {
    
    
        if(!head || !head->next)
            return 1;
        ListNode *fast = head, *slow = head;
        ListNode *p, *pre = NULL;
        while(fast && fast->next){
    
    
            p = slow;
            slow = slow->next;    //快慢遍历
            fast = fast->next->next;

            p->next = pre;  //翻转
            pre = p;
        }
        if(fast)  //奇数个节点时跳过中间节点
            slow = slow->next;

        while(p){
    
           //前半部分和后半部分比较
            if(p->val != slow->val)
                return 0;
            p = p->next;
            slow = slow->next;
        }
        return 1;
    }
};

猜你喜欢

转载自blog.csdn.net/u013354486/article/details/107096099