leetcode[力扣]题目收集

1.应用场景/目的

1.锻炼与提升个人解决问题的能力

2.应对面试

 

备注:

周一, 周三, 周五实现一道算法 //比较简单的就不再收录

2.学习/操作

1.给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。//20191116 上沙 

https://leetcode-cn.com/explore/interview/card/bytedance/242/string/1012/

示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

个人解法:

[实现语言: PHP]

class Solution {

    /**
     * @param String $s
     * @return Integer
     */
    public function lengthOfLongestSubstring($s) {
        $array = [];
        $count = strlen($s);
        for($i=0; $i<$count; $i++){
            if($i === 0){
                $array[] = $s[$i];
                continue;
            }
            if(in_array($s[$i], $array)){
               break;
            }
            $array[] = $s[$i];
        }
        return count($array);                 
    }    
}

 

备注: 

将代码直接copy在编辑代码区域, 然后点击执行, 观察结果即可.

 

解答:  //执行时间挺快的, 内存消耗为什么会这么多, 另外这个并不是时空复杂度分析  TBD

即滑动窗口解法

//    执行用时 :12 ms, 在所有 PHP 提交中击败了97.99%的用户
//    内存消耗 :14.5 MB, 在所有 PHP 提交中击败了97.82%的用户

class Solution {

 

    /**

     * @param String $s

     * @return Integer

     */

     function lengthOfLongestSubstring($s) {

          $lens = strlen($s);//字符串长度

          $tmp  = ''; //用于存储子串,不包含有重复的字符

          $len  = 0; //最长子串的长度

          for($i=0; $i<$lens; $i++) {

              $re = strpos($tmp,$s[$i]);//判断是否有重复字符

              if(false !== $re) {//有重复

                  $tmp .= $s[$i];//先追加上去 例如pwasw

                  $tmp = substr($tmp,$re+1);//从重复位置开始 截取后 pwasw=>asw

              }else {//无重复字符

                  $tmp .= $s[$i];//追加到后面

              }

              //每一次过去后,比较当前的tmp 与上一次的 len 谁更大

              $len = strlen($tmp)>$len ? strlen($tmp) : $len;

          }

          return $len;//返回最后子串长度

    }

}


/*
[substr]    https://www.php.net/manual/zh/function.substr.php
[strpos]    https://www.php.net/manual/zh/function.strpos.php
*/

 

解法:

有三种思路:

详见: https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-by-leetcod/

 

分别为:  TBD

暴力法  TEL(Time Limit Exceeded) 超过时间限制

滑动窗口

优化的滑动窗口

 

 

2.两数之和   算法 //20191117

详情:  https://leetcode-cn.com/problems/two-sum/

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

 

个人解法:

class Solution {

 

    /**

     * @param Integer[] $nums

     * @param Integer $target

     * @return Integer[]

     */

    function twoSum($nums, $target) {

        $count = count($nums);

        for($i=0; $i<$count; $i++){

            for($j=$i+1; $j<$count; $j++){

                if($nums[$i] + $nums[$j] === $target){

                    return [$i, $j];

                }

            }

        }

        return [0, 0];

    }

}

 

结果:

通过  用时1616 ms, 内存15.9 MB

 

参考他人实现

https://leetcode-cn.com/problems/two-sum/solution/php-zui-shao-yong-shi-64msxun-huan-yi-ci-jie-ti-si/

 

暴露问题:

1.代码书写不认真

2.代码时空复杂度很高

 

最佳实现:

最少用时8ms, 内存 16 MB

 

class Solution {

    /**
     * @param Integer[] $nums
     * @param Integer $target
     * @return Integer[]
     */
    function twoSum($nums, $target) {
        $found = [];
        
        foreach ($nums as $key => $val) {
            $diff = $target - $val;
            
            if (!isset($found[$diff])) {  //isset的内部实现原理是什么? 是否是循环遍历? TBD
                $found[$val] = $key;
                continue;
            }
            
            return [$found[$diff], $key];
        }
    }
}

 

3.两数相加   算法 //20191118 上沙 

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

详情:  https://leetcode-cn.com/problems/add-two-numbers/solution/liang-shu-xiang-jia-by-leetcode/

 

结果:

没写出来

 

参考他人实现: 

https://leetcode-cn.com/problems/add-two-numbers/solution/php-dan-lian-biao-liang-shu-xiang-jia-ti-jie-12ms-/

code:  //重点在于深拷贝 浅拷贝 指针重点在于深拷贝 浅拷贝 指针

/**

 * Definition for a singly-linked list.

 * class ListNode {

 *     public $val = 0;

 *     public $next = null;

 *     function __construct($val) { $this->val = $val; }

 * }

 */

class Solution {

 

    /**

     * @param ListNode $l1

     * @param ListNode $l2

     * @return ListNode

     */

    function addTwoNumbers($l1, $l2) {

        $listNode = new ListNode(0);

        $l = $listNode;

        $a = 0;

 

        do {

            $v1 = $l1->val ?? 0;

            $v2 = $l2->val ?? 0;

            $res = $v1 + $v2 + $a;

            $a = floor($res/10);            

            $l->next = new ListNode($res%10);

            $l = $l->next;

            $l1 = $l1->next;

            $l2 = $l2->next;

        } while ($l1 || $l2 || $a);

 

        return $listNode->next;

    }

}

 

提交结果:

执行用时 :24 ms, 在所有 php 提交中击败了62.03%的用户

内存消耗 :15 MB, 在所有 php 提交中击败了10.05%的用户

 

暴露问题:

1.链表不熟悉

2.解题思路没有,PHP语法有些不是很熟悉

 

最佳实现:

官方解答:  //初等数学 TBD

https://leetcode-cn.com/problems/add-two-numbers/solution/liang-shu-xiang-jia-by-leetcode/


4.第二高的薪水 数据库  20191120 上沙 

编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。

+----+--------+
| Id | Salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+
例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null。

+---------------------+
| SecondHighestSalary |
+---------------------+
| 200                 |

 

详细: https://leetcode-cn.com/problems/second-highest-salary/

官网解答: https://leetcode-cn.com/problems/second-highest-salary/solution/di-er-gao-de-xin-shui-by-leetcode/

 

答案

方法一:使用子查询和 LIMIT 子句
算法

将不同的薪资按降序排序,然后使用 LIMIT 子句获得第二高的薪资。

MySQL
SELECT DISTINCT
    Salary AS SecondHighestSalary
FROM
    Employee
ORDER BY Salary DESC
LIMIT 1 OFFSET 1
然而,如果没有这样的第二最高工资,这个解决方案将被判断为 “错误答案”,因为本表可能只有一项记录。为了克服这个问题,我们可以将其作为临时表。//没有想到数据表只有一行数据导致时, 导致问题 , 另外看到答案也想到IFNULL 

MySQL
SELECT
    (SELECT DISTINCT
            Salary
        FROM
            Employee
        ORDER BY Salary DESC
        LIMIT 1 OFFSET 1) AS SecondHighestSalary;


方法二:使用 IFNULL 和 LIMIT 子句
解决 “NULL” 问题的另一种方法是使用 “IFNULL” 函数,如下所示。

MySQL
SELECT
    IFNULL(
      (SELECT DISTINCT Salary
       FROM Employee
       ORDER BY Salary DESC
        LIMIT 1 OFFSET 1),
    NULL) AS SecondHighestSalary

 

 

5.第N高的薪水  20191123

https://leetcode-cn.com/problems/nth-highest-salary/solution/jing-que-da-an-han-zhu-shi-kao-lu-nbu-he-li-qing-k/

 

解答:

查询思路类似求第二高的薪水,需注意考虑N不合理的情况。测试第一轮就遇到N为0的情况,所以加上了处理逻辑。

详细如下://存储过程, 这个没有认真学习, 操作过, 所以还是要认真学习下. TBD

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
    DECLARE P1 INT; -- 第P1高的薪水
    DECLARE P2 INT; -- 取P1-1后的P2个值
    -- 当N<1时,P1会为负数,采用IF调整为0,另此时结果不存在,设置P2为0
    IF (N<1)
      THEN SET P1 = 0, P2 = 0;
    ELSE SET P1 = N-1, P2 = 1;
    END IF;
    
    RETURN (
        -- 若不存在第N高的薪水,取NULL
        SELECT IFNULL(
            (
                -- 去除重复值,倒序取第P1大的值后P2个值
               SELECT DISTINCT Salary
                FROM Employee
                ORDER BY Salary DESC
                LIMIT P1, P2
            ), NULL
        ) AS SecondHighestSalary   
    );
END

 

 

 

6.分数排名  20191125 上沙 周一 

方法一:

//最简单的语句, 注意,mysql版本8已至此窗口函数这个功能,虽然在leetcode上运行不成功,可能的原因是后台的mysql数据库版本不是最新的。

select score, 

    dense_rank() over(order by Score desc) as Rank

from Scores;

 

方法二: //执行失败!  语法还没有看明白!

链接: https://leetcode-cn.com/problems/rank-scores/solution/chao-rong-yi-li-jie-qie-gao-xiao-lu-by-ai-gua-cai-/

容易理解的语句,且效率高于99%
首先根据任务进行分析,目的进行连续的并列排序,并且以整型的字段返回。
语句执行顺序为 from -> oder by -> select (这是每个查询执行的顺序,子查询也一样)
对分数进行判断,相同即排名不变,不相同排名加一。使用if语句进行判断,ex:if(a>1,A,B) 如果为真返回A,反之返回B


SELECT Score, Rank FROM
(SELECT Score,
@curRank := IF(@prevRank = Score, @curRank+0,@curRank:=@curRank+1) AS Rank,
@prevRank := Score
FROM Scores, (
SELECT @curRank :=0, @prevRank := NULL
) r
ORDER BY Score DESC) s;

 

执行成功: //语法没看明白!

select  Score,

((case 

when @prevRank = Score then @curRank

when @prevRank := Score then @curRank:=@curRank +1 

else @curRank:=@curRank +1

end )*1) as Rank

FROM Scores,(select @curRank:=0,@prevRank:=NULL) p

ORDER BY Score desc

 

7.180. 连续出现的数字  20191127 上沙 周三

https://leetcode-cn.com/problems/consecutive-numbers/

 

8.182. 查找重复的电子邮箱  20191129 上沙 周五

https://leetcode-cn.com/problems/duplicate-emails/

最简答的答案:

SELECT

    Email

FROM

    Person

group by Email

having count(Email) > 1;

 

个人答案: 有想到group by 和having 但是想复杂了[运用笛卡尔积来做]

 

9.181. 超过经理收入的员工  20191202 上沙 周一

https://leetcode-cn.com/problems/employees-earning-more-than-their-managers/

官网两种答案都有想到,并通过。

 

10.183. 从不订购的客户   20191204 上沙 周三

https://leetcode-cn.com/problems/customers-who-never-order/solution/cong-bu-ding-gou-de-ke-hu-by-leetcode/

官网答案确实有点平常了,尽管个人答案也是如此.

 

11.184. 部门工资最高的员工   20191206 上沙 周五

https://leetcode-cn.com/problems/department-highest-salary/solution/bu-men-gong-zi-zui-gao-de-yuan-gong-by-leetcode/

笔记:

SELECT
    Department.name AS 'Department',
    Employee.name AS 'Employee',
    Salary
FROM
    Employee
        JOIN
    Department ON Employee.DepartmentId = Department.Id
WHERE
    (Employee.DepartmentId , Salary) IN
    (   SELECT
            DepartmentId, MAX(Salary)
        FROM
            Employee
        GROUP BY DepartmentId
    )
;

第一次见 可以两个字段in的 长见识了  //看手册还是要认真看下详细用法, 这是绝大数人的弊端. 也是区别人与人的方式.

 

12.185. 部门工资前三高的所有员工  20191209 上沙 周一

https://leetcode-cn.com/problems/department-top-three-salaries/

# Write your MySQL query statement below

 

-- 个人没有解出来

 

-- 方法一  //推荐, 但实际开发中可考虑使用语言处理

SELECT

    d.NAME AS 'Department',

    e1.NAME AS 'Employee',

    e1.Salary 

FROM

    Employee e1

    JOIN Department d ON e1.DepartmentId = d.Id 

WHERE

    3 > (

    SELECT

        COUNT( DISTINCT e2.Salary ) -- DISTINCT是为了并列名次算做同一个

        

    FROM

        Employee e2 

    WHERE

        e2.Salary > e1.Salary 

    AND e1.DepartmentId = e2.DepartmentId 

    );


 

-- 方法二

SELECT

    Department.NAME AS Department,

    e1.NAME AS Employee,

    e1.Salary AS Salary 

FROM

    Employee AS e1, Department 

WHERE

    e1.DepartmentId = Department.Id 

    AND 3 > (SELECT  count( DISTINCT e2.Salary ) 

             FROM   Employee AS e2 

             WHERE  e1.Salary < e2.Salary   AND e1.DepartmentId = e2.DepartmentId   ) 

ORDER BY Department.NAME,Salary DESC;

 

协助理解:

解题思路:
回忆一下 count 函数

MySql
count(字段名)  # 返回表中该字段总共有多少条记录
回忆一下 DISTINCT 关键字

MySql
DISTINCT 字段名   # 过滤字段中的重复记录
我们先找出公司里前 3 高的薪水,意思是不超过三个值比这些值大

MySql
SELECT e1.Salary 
FROM Employee AS e1
WHERE 3 > 
        (SELECT  count(DISTINCT e2.Salary) 
         FROM    Employee AS e2 
          WHERE    e1.Salary < e2.Salary     AND e1.DepartmentId = e2.DepartmentId) ;
举个栗子:
当 e1 = e2 = [4,5,6,7,8]

e1.Salary = 4,e2.Salary 可以取值 [5,6,7,8],count(DISTINCT e2.Salary) = 4

e1.Salary = 5,e2.Salary 可以取值 [6,7,8],count(DISTINCT e2.Salary) = 3

e1.Salary = 6,e2.Salary 可以取值 [7,8],count(DISTINCT e2.Salary) = 2

e1.Salary = 7,e2.Salary 可以取值 [8],count(DISTINCT e2.Salary) = 1

e1.Salary = 8,e2.Salary 可以取值 [],count(DISTINCT e2.Salary) = 0

最后 3 > count(DISTINCT e2.Salary),所以 e1.Salary 可取值为 [6,7,8],即集合前 3 高的薪水

再把表 Department 和表 Employee 连接,获得各个部门工资前三高的员工。

MySql
SELECT
    Department.NAME AS Department,
    e1.NAME AS Employee,
    e1.Salary AS Salary 
FROM
    Employee AS e1,Department 
WHERE
    e1.DepartmentId = Department.Id 
    AND 3 > (SELECT  count( DISTINCT e2.Salary ) 
             FROM    Employee AS e2 
             WHERE    e1.Salary < e2.Salary     AND e1.DepartmentId = e2.DepartmentId     ) 
ORDER BY Department.NAME,Salary DESC;

 

 

 

 

 

 

 

 

 

 

后续补充

...


后续补充

以下是模板

结果:

通过  用时1616 ms, 内存15.9 MB

 

参考他人实现: 

https://leetcode-cn.com/problems/two-sum/solution/php-zui-shao-yong-shi-64msxun-huan-yi-ci-jie-ti-si/

 

暴露问题:

1.代码书写不认真

2.代码时空复杂度很高

 

最佳实现:

....

 

3.问题

1.相同算法, 实现语言不同, 效率如何? //时间复杂度  20191118 周一

同一个算法, 实现预言的级别越高, 执行效率就越低.

 

2.实际开发中, 写算法, 时间复杂度考虑的是哪个指标? 最好/最坏/平均时间复杂度?

最坏时间复杂度. 时间复杂度总是考虑在最坏情况下的时间复杂度,以保证算法的运行时间不会比它更长. 

严蔚敏教材中原话, 虽然讨论多年,对于这种在语言层次上的效率问题,建议不要以特例来解释其优劣, 该结论肯定是没有错误的.

另外,思考原因/原理

 

实际上,在大多数情况下,我们并不需要区分最好、最坏、平均情况时间复杂度三种情况。

很多时候,我们使用一个复杂度就可以满足需求了。只有同一块代码在不同的情况下,时间复杂度有量级的差距,我们才会使用这三种复杂度表示法来区分。

 

3.isset的内部实现原理是什么? 是否是循环遍历? 

在求解[两数之和]算法题目时, 使用isset 时间复杂度就降下来, 想知道PHP的isset()内部实现机制  TBD

 

 

TBD

4.参考

https://leetcode-cn.com/explore/interview/card/bytedance/242/string/1012/  //详细题目-字节跳动

https://time.geekbang.org/column/article/40447   //极客时间-数据结构与算法之美

王道系列-数据结构

后续补充

...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值