力扣日常练习

搜索插入位置(简单)

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

解题:

简单的二分查找问题,由于我们知道当排序数组当中存在目标值的情况,则直接返回mid下标即可,当排序数组当中不包含目标值,此时我们可以分析得出,while循环的倒数第一次中,必定left=right,此时定位到的元素一定为第一个比target目标值大的元素,紧接着right值减一,退出while循环。故我们可以知道此时left下标对应的元素为target目标值应该插入的位置。

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        while(left <= right) {
            int mid = left + ((right - left) >> 1);
            if(nums[mid] == target) {
                return mid;
            }
            else if(nums[mid] < target) {
                left = mid + 1;
            }
            else {
                right = mid - 1;
            }
        }
        return left;
    }

};

外观数列(简单)

「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下:

外观数列
1 1
2 11
3 21
4 1211
5 111221

其中:

  • 1 被读作  "one 1"  ("一个一") , 即 11。
  • 11 被读作 "two 1s" ("两个一"), 即 21。
  • 21 被读作 "one 2",  "one 1" ("一个二" ,  "一个一") , 即 1211。

给定一个正整数 n(1 ≤ n ≤ 30),输出外观数列的第 n 项。

注意:整数序列中的每一项将表示为一个字符串。

解题:

这道题其实并不难,重要的是理解题意,想起来好像在之前美团线下面试的时候被问到了这道题,当时是以一道智力题的方式给出外观数列的前五项,让我写出第六项,当时没有反应过来,现在回过头来才发觉原来正是这道外观数列题的抽象。话不多说,接下来分析这道题:外观数列其实就是重复的对上一个数进行描述的数列,我们举例来说明:

  • 首先第一个数为1,该数事先给出;
  • 接下来第二个数对第一个数1进行描述,1当中有1个1,因此第二个数为11;
  • 接下来第三个数对第二个数11进行描述,11当中有2个1,因此第三个数为21;
  • 接下来第四个数对第三个数21进行描述,21当中有1个2以及1个1,因此第四个数为1211;
  • 接下来第五个数对第四个数1211进行描述,1211当中有1个1以及1个2以及2个1,因此第五个数为111221。

这下我们总算理解了题意,开始我们的代码:

class Solution {
public:
    string countAndSay(int n) {
        string str, res;
        res = "1";
        if (n == 1) return res;
        for (int i = 1; i < n; ++i)
        {   
            str = res;
            res = "";
            for (int j = 0; j < str.size();)
            {
                // c为计数器,k为当前描述数字对应下标
                int c=0,k=j;
                // 若k合法且str[k]重复则计数
                while(k<str.size()&&str[k]==str[j])
                {
                    ++k;
                    ++c;
                }
                res+=to_string(c)+str[j];
                j=k;
            }
        }
        return res;
    }
};

最后一个单词的长度(简单)

给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。

如果不存在最后一个单词,请返回 0 。

说明:一个单词是指由字母组成,但不包含任何空格的字符串。

解题:

这道题的重点在于对于特殊情况的考虑:

  • 第一种情况,"Hello World",此时返回最后一个单词World的长度5
  • 第二种情况,"Hello World ",此时需要先处理尾空格后,返回最后一个单词World的长度5

分析好特殊情况后,开始编写代码:

class Solution {
public:
    int lengthOfLastWord(string s) {
        int last = s.size();
        for(int i = s.size() - 1; i >= 0; --i)
        {
            if(s[i] == ' ')
                last = i;
            else
                break;
        }
        int flag = 0;
        for(int i = 0; i < last; ++i)
        {
            if(s[i] == ' ')
            {
                flag = i + 1;
            }
        }
        return last - flag;
    }
};

二进制求和(简单)

给定两个二进制字符串,返回他们的和(用二进制表示)。

输入为非空字符串且只包含数字 1 和 0

解题:

反向求和,为空补0,标记进位数。

class Solution {
public:
    string addBinary(string a, string b) {
        string ans = "";
        int ca = 0;
        for(int i = a.size() - 1, j = b.size() - 1; i >= 0 || j >= 0; --i, --j)
        {
            int sum = ca;
            sum += i >= 0 ? a[i] - '0' : 0;
            sum += j >= 0 ? b[j] - '0' : 0;
            ans = to_string(sum % 2) + ans;
            ca = sum / 2;
        }
        if (ca == 1)
            ans = to_string(ca) + ans;
        return ans;
    }
};

x的平方(简单)

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

解题:

这道题也称为牛顿法,换而言之也就是二分查找的变形问题。之前有一篇博客就是关于二分查找的,可以具体去看那篇博客。

class Solution {
public:
    int mySqrt(int x) {
        long left = 0, right = x/2 + 1;
        while(left <= right)
        {
            long mid = left + ((right - left) >> 1);
            if(mid * mid > x)
            {
                right = mid - 1;
            }
            else
            {
                if((mid == x/2 + 1) || (mid+1) * (mid+1) > x)
                    return mid;
                else
                    left = mid + 1;
            }
        }
        return -1;
    }
};

爬楼梯(简单)

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

解题:

简单的推导问题,推导出公式:A[n] = A[n-1] + A[n-2]进而求解:

class Solution {
public:
    int climbStairs(int n) {
        if (n < 3)
            return n;
        const int len = n+1;
        int a[len];
        a[1] = 1;
        a[2] = 2;
        for(int i = 3; i <= n; ++i)
        {
            a[i] = a[i-1] + a[i-2];
        }
        return a[n];
    }
};

删除排序链表中的重复元素(简单)

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode* current = head;
        while (current != nullptr && current->next != nullptr) {
            if (current->next->val == current->val) {
                current->next = current->next->next;
            } else {
                current = current->next;
            }
        }
        return head;
    }
};

相同的树(简单)

给定两个二叉树,编写一个函数来检验它们是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

解题:

递归求解即可:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSameTree(TreeNode* p, TreeNode* q) {
        if(p == nullptr && q == nullptr)
            return true;
        else if(p == nullptr || q == nullptr)
            return false;
        else if(p->val != q->val)
            return false;
        return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
    }
};
发布了37 篇原创文章 · 获赞 42 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42570248/article/details/103956338