leetcode题目——边做边记录

1. 20200602——求1+2+…+n

面试题64. 求1+2+…+n
求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

  • 解法1:用&&或||的短路特性实现递归
    • 将判断是否为递归的出口看作 A && B 表达式中的 A 部分,递归的主体函数看作 B 部分。如果不是递归出口,则返回 \textit{True}True,并继续执行表达式 B 的部分,否则递归结束。当然,你也可以用逻辑运算符 || 给出类似的实现,这里我们只提供结合逻辑运算符 && 的递归实现。
  • 解法2:俄罗斯农民乘法,根据数的范围手动循环
    • 考虑 A 和 B 两数相乘的时候我们如何利用加法和位运算来模拟,其实就是将 B 二进制展开,如果 B 的二进制表示下第 ii 位为 1,那么这一位对最后结果的贡献就是 A*(1<<i)A∗(1<<i) ,即 A<<iA<<i。我们遍历 B 二进制展开下的每一位,将所有贡献累加起来就是最后的答案,这个方法也被称作「俄罗斯农民乘法」
    • [1,10000],所以 nn 二进制展开最多不会超过 1414 位,我们手动展开 1414 层代替循环即可

2. 20200605——除自身以外数组的乘积

238. 除自身以外数组的乘积
给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

示例:

输入: [1,2,3,4]
输出: [24,12,8,6]

提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。

说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。

进阶:
你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)

class Solution {
    // public int[] productExceptSelf(int[] nums) {
    //     int n = nums.length;
    //     int[] left = new int[nums.length];
    //     int[] right = new int[nums.length];
    //     left[0] = 1;
    //     for(int i = 1;i<n;i++){
    //         left[i] = left[i-1]*nums[i-1];
    //     }
    //     // System.out.println(Arrays.toString(left));
    //     right[n-1] = 1;
    //     for(int i = n-2;i>=0;i--){
    //         right[i] = right[i+1]*nums[i+1];
    //     }
    //     // System.out.println(Arrays.toString(right));
    //     int[] res = new int[n];
    //     for(int i = 0;i<n;i++){
    //         res[i] = left[i]*right[i];
    //     }
    //     return res;
    // }

    // left O(n)变为 O(1)
    // public int[] productExceptSelf(int[] nums) {
    //     int n = nums.length;
    //     // int[] left = new int[nums.length];
    //     int[] right = new int[nums.length];
    
    //     // System.out.println(Arrays.toString(left));
    //     right[n-1] = 1;
    //     for(int i = n-2;i>=0;i--){
    //         right[i] = right[i+1]*nums[i+1];
    //     }
    //     int left = 1;
    //     // System.out.println(Arrays.toString(right));
    //     int[] res = new int[n];
    //     for(int i = 0;i<n;i++){
    //         res[i] = left*right[i];
    //         left *= nums[i];
    //     }
    //     return res;
    // }

    // right 提前放到res里面去
    public int[] productExceptSelf(int[] nums) {
        int n = nums.length;
        // int[] left = new int[nums.length];
        // int[] right = new int[nums.length];
    
        int[] res = new int[n];
        // System.out.println(Arrays.toString(left));
        res[n-1] = 1;
        for(int i = n-2;i>=0;i--){
            res[i] = res[i+1]*nums[i+1];
        }
        int left = 1;
        // System.out.println(Arrays.toString(right));
        for(int i = 0;i<n;i++){
            res[i] = left*res[i];
            left *= nums[i];
        }
        return res;
    }
}

3. 接雨水

42. 接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
在这里插入图片描述
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

  • 解法一:单调栈
  • 解法二:双指针

4. 20200609——灯泡开关

319. 灯泡开关

初始时有 n 个灯泡关闭。 第 1 轮,你打开所有的灯泡。 第 2 轮,每两个灯泡你关闭一次。 第 3
轮,每三个灯泡切换一次开关(如果关闭则开启,如果开启则关闭)。第 i 轮,每 i 个灯泡切换一次开关。 对于第 n
轮,你只切换最后一个灯泡的开关。 找出 n 轮后有多少个亮着的灯泡。

示例:

输入: 3
输出: 1
解释: 初始时, 灯泡状态 [关闭, 关闭, 关闭]. 第一轮后, 灯泡状态 [开启, 开启, 开启].
第二轮后, 灯泡状态 [开启, 关闭, 开启]. 第三轮后, 灯泡状态 [开启, 关闭, 关闭].

你应该返回 1,因为只有一个灯泡还亮着。
Related Topics 脑筋急转弯 数学

思路:完全平方数的灯泡会亮着。
举例:

  • 第3个灯泡:3=1*3,第1次被打开,第3次被关上。同理所有质数。
  • 第4个灯泡:4=14=22,第1次被打开,第2次被关上,第4次被打开。(完全平方数)
  • 第24个灯泡:24=124=212=38=46,所以是关闭的。
return (int)Math.pow(n,1/2d);

5. 20200613——三数之和

15. 三数之和
前置题:两数之和
思路:结合两数之和的思路,即排序后,从头选定一个数,再从尾部选定一个数,双指针。对于三数则是,选定第一个数a[i],第二个数则从i+1作为头部,再头尾双指针。

法一:

public List<List<Integer>> threeSum2(int[] nums) {
        List<List<Integer>> list = new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0;i<nums.length;i++){
            if (i>0&&nums[i]==nums[i-1]) continue;
            int k = nums.length-1;
            for(int j=i+1;j<nums.length;j++){
                if (j>i+1&&nums[j]==nums[j-1]) continue;
                while (k>j && nums[k]+nums[i]+nums[j]>0){
                    k--;
                }
                if (k==j){
                    break;
                }
                if (nums[k]+nums[i]+nums[j]==0){
                    List<Integer> li = new ArrayList<>();
                    li.add(nums[i]);
                    li.add(nums[j]);
                    li.add(nums[k]);
                    list.add(li);
                }
            }

        }

        return list;
    }

法二:结合hashmap

public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> list = new ArrayList<>();
        HashMap<Integer,Integer> map = new HashMap<>();
        HashSet<Integer> used = new HashSet<>();
        Arrays.sort(nums);
        for(int i=0;i<nums.length;i++){
            if (i>0&&nums[i]==nums[i-1]) continue;
            for(int j=i+1;j<nums.length;j++){
//                if (j>0&&nums[j]==nums[j-1]) continue;
                if(map.containsKey(-nums[j]) && !used.contains(-nums[j])){
                    List<Integer> li = new ArrayList<>();
                    li.add(nums[i]);
                    li.add(nums[j]);
                    li.add(nums[map.get(-nums[j])]);
                    list.add(li);
                    used.add(-nums[j]);
                }else{
                    map.put(nums[i]+nums[j],j);
                }
            }
            map.clear();
            used.clear();
        }

        return list;
    }

力扣运行结果:

  • 法一:24ms,44.3MB
  • 法二:212ms,44.2MB

6. 20201023——回文链表

234. 回文链表

用双指针,边移动边逆转链表能达到 时间O(n) 空间O(1)的要求。
官方题解 的解法二虽然复杂度不及上面,但对递归的使用很巧妙。

class Solution {
    private ListNode frontPointer;

    private boolean recursivelyCheck(ListNode currentNode) {
        if (currentNode != null) {
            if (!recursivelyCheck(currentNode.next)) {
                return false;
            }
            if (currentNode.val != frontPointer.val) {
                return false;
            }
            frontPointer = frontPointer.next;
        }
        return true;
    }

    public boolean isPalindrome(ListNode head) {
        frontPointer = head;
        return recursivelyCheck(head);
    }
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/palindrome-linked-list/solution/hui-wen-lian-biao-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值