LeetCode Hot 100~Day2

news2024/11/19 3:44:16

目录

三数之和

电话号码的字母组合

括号生成

合并k个升序链表 

下一个排列 

搜索旋转排序数组 

在排序数组中查找元素的第一个和最后一个位置 

组合总数 

全排列

旋转图像


三数之和

题目链接:15.三数之和

 示例

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

解题思路

双指针思想,先对数组进行排序,排序后从第一个位置开始枚举,需要确保下一个枚举的数不等于本次枚举的数,如果相等,得到的结果是相同的。 

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        int n = nums.length;
        Arrays.sort(nums);
        List<List<Integer>> ret = new ArrayList<>();
        for (int first = 0; first < n; first++) {
            //保证与上一次枚举的数不同
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            int third = n - 1;
            int target = -nums[first];
            //-4 -1 -1 0 1 2
            for (int second = first + 1; second < nums.length; second++) {
                //保证与上一次枚举的不同
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue;
                }
                //保证second在third的左边
                while (second < third && nums[second] + nums[third] > target) {
                    third--;
                }
                //指针重合就退出循环
                if (second == third) {
                    break;
                }
                if (nums[second] + nums[third] == target) {
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[first]);
                    list.add(nums[second]);
                    list.add(nums[third]);
                    ret.add(list);
                }
            }
        }
        return ret;
    }
}

电话号码的字母组合

题目链接:17.电话号码的字母组合

示例

输入:digits = "23"

输出:["ad","ae","af","bd","be","bf","cd","ce","cf"] 

解题思路 

维护一个深度和当前的可能的字母组合,当输入的数字长度等于深度时,就将当前的字母组合加入到结果集中,结束该路径并继续向上回溯;根据深度找到当前的数字,再根据这个数字得到该数字所代表的字符,依次遍历每一种可能,直至所有字符遍历结束。

class Solution {
    String[] mapString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    List<String> ret = new ArrayList<>();
    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) {
            return ret;
        }
        StringBuilder s = new StringBuilder("");
        dfs(digits, s, 0);
        return ret;
    }

    private void dfs(String digits, StringBuilder s, int depth) {
        if (depth == digits.length()) {
            ret.add(s.toString());
            return;
        }
        int index = digits.charAt(depth) - '0';
        String curMap = mapString[index];
        for (int i = 0; i < curMap.length(); i++) {
            dfs(digits, s.append(curMap.charAt(i)), depth + 1);
            s.deleteCharAt(s.length() - 1);
        }
    }
}

括号生成

题目链接: 22.括号生成

解题思路

回溯思想,只在序列有效时添加括号,通过跟踪当前的左括号和右括号数来实现,如果左括号数量不大于n,添加左括号,如果右括号数量小于左括号,添加左括号,当括号数量等于2*n,加入结果集 

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> ret = new ArrayList<>();
        dfs(ret, new StringBuilder(), 0, 0, n);
        return ret;
    }

    private void dfs(List<String> ret, StringBuilder cur, int open, int close, int n) {
        if (cur.length() == n * 2) {
            ret.add(cur.toString());
            return;
        }
        if (n > open) {
            cur.append('(');
            dfs(ret, cur, open + 1, close, n);
            cur.deleteCharAt(cur.length() - 1);
        }
        if (open > close) {
            cur.append(')');
            dfs(ret, cur, open, close + 1, n);
            cur.deleteCharAt(cur.length() - 1);
        }
    }
}

合并k个升序链表 

题目链接:23.合并k个升序链表

 解题思路

分治思想,要合并k个升序链表,则首先将每两个链表合并,第一轮合并过后,继续两两合并,直至得到最终结果。

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        return merge(lists, 0, lists.length - 1);
    }
    private ListNode merge(ListNode[] lists, int start, int end) {
        if (start == end) {
            return lists[end];
        }
        int mid = (start + end) / 2;
        ListNode l1 = merge(lists, start, mid);
        ListNode l2 = merge(lists, mid + 1, end);
        return mergeTwoList(l1, l2);
    }
    private ListNode mergeTwoList(ListNode l1, ListNode l2) {
        if (l1 == null || l2 == null) {
            return l1 == null ? l2 : l1;
        }
        if (l1.val > l2.val) {
            l2.next = mergeTwoList(l1, l2.next);
            return l2;
        } else {
            l1.next = mergeTwoList(l1.next, l2);
            return l1;
        }
    }
}

下一个排列 

题目链接:31.下一个排列

 示例

输入:nums = [1,2,3]

输出:[1,3,2]

解题思路:将左边的一个较小数与右边的一个较大数进行交换,需要满足左边的较小数尽可能靠右,较大数尽可能的小,再交换结束后,再将较大数右边的数按照升序重新排列即可 

class Solution {
    public void nextPermutation(int[] nums) {
        //8 5 3 6 2 1
        int i = nums.length - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        if (i >= 0) {
            int j = nums.length - 1;
            while (j >= 0 && nums[j] <= nums[i]) {
                j--;
            }
            swap(nums, i, j);
        }
        reverse(nums, i + 1);
    }
    private void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
    private void reverse(int[] nums, int start) {
        int end = nums.length - 1;
        while (start < end) {
            swap(nums, start, end);
            start++;
            end--;
        }
    }
}

搜索旋转排序数组 

题目链接:33. 搜索旋转排序数组

 

示例

输入:nums = [4,5,6,7,0,1,2], target = 0

输出:4

解题思路:二分思想,查找相当于是不断地缩小范围,通过nums[mid]、nums[left]、nums[right]、target的对比,不断缩小范围,直至获得结果或者左边界left > 右边界right为止.

class Solution {
    //1 2 3 4 5
    //2 3 4 5 1
    //5 1 2 3 4
    public int search(int[] nums, int target) {
        if (nums.length == 0 || nums == null) {
            return -1;
        }
        if (nums.length == 1) {
            return nums[0] == target ? 0 : -1;
        }
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] == target) {
                return mid;
            }
            if (nums[left] <= nums[mid]) {
                if (nums[mid] >= target && nums[left] <= target) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            } else {
                if (nums[right] >= target && nums[mid] <= target) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
}

在排序数组中查找元素的第一个和最后一个位置 

题目链接:34. 在排序数组中查找元素的第一个和最后一个位置

 

 示例

输入:nums = [5,7,7,8,8,10], target = 8

输出:[3,4]

输入:nums = [5,7,7,8,8,10], target = 6

输出:[-1,-1]

解题思路:二分查找,查找第一个大于等于target的下标位置,即为第一个位置,查找第一个大于target的下标,即为最后一个位置,因为可能不存在target,因此在查询结束后验证一下left和right下标对应的值是否为target,如果是则输出,left,right,反之输出-1,-1. 

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left = binarySearch(nums, target, true);
        int right = binarySearch(nums, target, false) - 1;
        if (left <= right && right < nums.length && nums[left] == target && nums[right] == target) {
            return new int[]{left, right};
        }
        return new int[]{-1, -1};
    }
    private int binarySearch(int[] nums, int target, boolean lower) {
        int left = 0;
        int right = nums.length - 1;
        int ret = nums.length;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] > target || (lower && nums[mid] >= target)) {
                right = mid - 1;
                ret = mid;
            } else {
                left = mid + 1;
            }
        }
        return ret;
    }
}

组合总数 

题目链接:39. 组合总和

 示例

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。

解题思路:由于同一个数字可以无限制重复被选取,因此每次从上一个位置开始搜索,边界值的设定:当目前的累加值大于给定的值就返回,当累加值等于给定的值就将其加入结果集中。 

class Solution {
    List<List<Integer>> ret = new ArrayList<>();
    List<Integer> curRet = new ArrayList<>();
    int curAdd = 0;
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        if (candidates == null || candidates.length == 0) {
            return ret;
        }
        dfs(candidates, target, 0);
        return ret;
    }
    private void dfs(int[] candidates, int target, int pre) {
        if (curAdd > target) {
            return;
        }
        if (curAdd == target) {
            ret.add(new ArrayList<>(curRet));
            return;
        }
        for(int i = pre; i < candidates.length; i++) {
            if (candidates[i] > target) {
                continue;
            }
            curRet.add(candidates[i]);
            curAdd += candidates[i];
            dfs(candidates, target, i);
            curAdd -= curRet.get(curRet.size() - 1);
            curRet.remove(curRet.size() - 1); 
        }
    }
}

全排列

题目链接:46. 全排列

 

示例

输入:nums = [1,2,3]

输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

解题思路:回溯算法,依次从每个位置开始添加元素,注意需要维护一个数组来记录每个下标对应的值是否已经添加到排列中,如果已经添加则不需要继续添加,反之,则添加入排列中。 

class Solution {
    List<List<Integer>> ret = new ArrayList<>();
    List<Integer> curRet = new ArrayList<>();
    public List<List<Integer>> permute(int[] nums) {
        if (nums == null || nums.length == 0) {
            return ret;
        }
        int[] visited = new int[nums.length];
        dfs(nums, visited);
        return ret;
    }
    private void dfs(int[] nums, int[] visited) {
        if (curRet.size() == nums.length) {
            ret.add(new ArrayList<>(curRet));
            return;
        }

        for (int i = 0; i < nums.length; i++) {
            if (visited[i] == 1) {
                continue;
            }
            visited[i] = 1;
            curRet.add(nums[i]);
            dfs(nums, visited);
            visited[i] = 0;
            curRet.remove(curRet.size() - 1);
        }
    }
}

旋转图像

题目链接:48. 旋转图像

 

解题思路:找规律问题,先水平翻转一次,再沿着对角线翻转一次即可得到结果 

class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        //水平翻转
        for (int i = 0; i < n / 2; i++) {
            for (int j = 0; j < n; j++) {
                int tmp = matrix[i][j];
                matrix[i][j] = matrix[n - i - 1][j];
                matrix[n - i - 1][j] = tmp;
            }
        }
        //对角线翻转
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                int tmp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = tmp;
            }
        }
    }
}

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/110947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

金山云将于12月30日在港交所上市:不发行新股,王育林已辞职

12月23日&#xff0c;金山云&#xff08;NASDAQ:KC&#xff0c;HK:03896&#xff09;发布公告称&#xff0c;拟通过介绍方式在港交所主板上市&#xff0c;代码为“03896”。按照计划&#xff0c;金山云将于2022年12月30日正式登陆港交所&#xff0c;不发行新股融资。 据贝多财…

我写这10+个JavaScript单行代码,被组长夸代码写得优雅!

大厂面试题分享 面试题库 前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 JavaScript 非常大的特点容易上手且非常灵活&#xff0c;代码实现方式五花八门&#xff1b;有时候能一行代码解决&#xff0c;就尽量不用…

MES系统与WMS系统的区别在哪里?

从字面上理解 MES是一套面向制造企业车间执行层的生产信息化管理系统。 WMS是仓储管理系统(WarehouseManagentsystem)的缩写&#xff0c;是通过入库、出库、调拨、管理等功能&#xff0c;实现一体化批量管理。 从用法上理解 WMS仓库管理系统主要采用条码技术&#xff0c;可及…

认识 微内核架构

微内核架构 1 说明背景 关于宏内核、微内核、混合内核&#xff0c;都是相对而言的概念。 宏内核: 通用的操作系统&#xff0c;将操作系统内核的所有模块放置在内核态运行&#xff0c;具备直接操作硬件的能力。例如 UNIX/Linux, FreeBSD 等微内核: 简单的操作系统&#xff0c;…

深度学习训练营之海贼王人物识别

深度学习训练营之海贼王人物识别原文链接环境介绍前置工作设置GPU导入数据数据查看数据预处理加载数据可视化数据检查数据配置数据集prefetch()功能详细介绍&#xff1a;归一化查看归一化后的数据构建VGG-16网络网络结构编译模型训练结果可视化原文链接 &#x1f368; 本文为&a…

ELK集群部署---ElasticSearch集群的部署

1. 环境规划&#xff1a; 主机名IP地址角色node1192.168.56.111 ElasticSearch(master) Zookeeper Kafka node2192.168.56.112 ElasticSearch(slave) Kibana Zookeeper Kafka node3192.168.56.113 ElasticSearch(slave) Zookeeper Kafka node4192.168.56.114 Logstash Filebe…

4. Json数据传递与接收

由于Json数据传递与接收在以后的开发中是主流&#xff0c;所以把它拿出来独立记一篇笔记&#xff0c;其他的笔记太庞杂了。 1. json数据参数传递实现步骤 1.1 添加json数据转换相关坐标 <dependency><groupId>com.fasterxml.jackson.core</groupId><ar…

HBCPC2022-河北省大学生程序设计竞赛

部分题解7-4 键盘故障7-6 筷子7-8 方7-9 优美的字符串7-4 键盘故障 签到题&#xff0c;直接遍历字符串&#xff0c;相同则跳过&#xff0c;不相同则输出 题目链接&#xff1a;https://pintia.cn/problem-sets/1584003400735793152/exam/problems/1584003481883000835 AC代码&a…

业聚医疗在港交所上市:市值约76亿港元,钱永勋、刘桂祯夫妇控股

12月23日&#xff0c;业聚医疗集团控股有限公司&#xff08;下称“业聚医疗”&#xff0c;HK:06929&#xff09;在港交所上市。本次上市&#xff0c;业聚医疗的发行价为8.80港元/股&#xff0c;全球发行发售5463.30万股&#xff0c;募集资金总额约为4.81亿港元&#xff0c;募资…

java基于ssm,jsp鞋城源码卖鞋服装男鞋商城女鞋商城项目源码

ssm开发的网上鞋城系统&#xff0c;主要有商品分类&#xff0c;列表&#xff0c;详情&#xff0c;加入购物车&#xff0c;订单&#xff0c;收货地址等功能&#xff0c;单商家登录后台可以发布商品&#xff0c;上下架商品&#xff0c;发货退款等管理订单。 演示视频&#xff1a;…

【开源项目】历史数据迁移

历史数据迁移 项目地址&#xff1a;https://gitee.com/xl-echo/dataMigration 历史迁移解决方案。微服务的架构为基础&#xff0c;使用多种设计模式&#xff0c;如&#xff1a;单利、桥接、工厂、模板、策略等。其中涉及的核心技术有&#xff0c;多线程、过滤器等。致力于解决…

django 中间件基础介绍

1、简单的理解&#xff0c;1个中间件就是1个类&#xff0c;中间件一般可以用来检查用户是否登录。 2、用户通过浏览器访问视图函数的内容需要先通过中间件&#xff0c;通过中间件后再到视图函数&#xff0c;返回结果也需要通过中间件&#xff0c;如下草图 3、自定义一个中间件…

一文读懂Linux内核处理器架构中的栈

栈是什么&#xff1f;栈有什么作用&#xff1f; 首先&#xff0c;栈 (stack) 是一种串列形式的 数据结构。这种数据结构的特点是 后入先出 (LIFO, Last In First Out)&#xff0c;数据只能在串列的一端 (称为&#xff1a;栈顶 top) 进行 推入 (push) 和 弹出 (pop) 操作。根据…

基于CNN卷积神经网络 猫狗图像识别

目录 一&#xff1a;数据集准备 二&#xff1a;读取自己的数据集 三&#xff1a;搭建网络 训练模型 四&#xff1a;猫狗图像识别 一&#xff1a;数据集准备 从官网下载比较麻烦&#xff0c;可根据以下链接&#xff0c;从百度网盘获取数据集 https://pan.baidu.com/s/13hw4L…

【Docker系列】容器环境配置

个人名片&#xff1a; 对人间的热爱与歌颂&#xff0c;可抵岁月冗长&#x1f31e; Github&#x1f468;&#x1f3fb;‍&#x1f4bb;&#xff1a;念舒_C.ying CSDN主页✏️&#xff1a;念舒_C.ying 个人博客&#x1f30f; &#xff1a;念舒_C.ying Docker可以让开发者打包他们…

55.函数的参数传递

55.函数的参数传递 文章目录55.函数的参数传递1.函数的参数2.参数的传递方法3.使用位置参数传递参数4.使用关键字传递参数1.函数的参数 自定义函数有2种参数&#xff1a;形式参数和实际参数。 def语句中的参数不是实际参数&#xff0c;我们称之为形式参数&#xff0c;简称形参…

C51——添加震动开盖功能,使用外部中断优化

void main() {double dis;Timer1Init();Time0Init();SG90_Init();while(1){dis get_dis();if(dis<10 || SW1 0||Vibrate 0){OpenTheLed5();opengaizi(); // }else{CloseTheLed5();closegaizi();}} }像这样只是简单的通过震动模块传给单片机一个让舵机转动&#xff0c;出来…

lvm 制作

壹&#xff1a; 创建LVM 逻辑卷 1&#xff0c;将物理盘格式为pv卷&#xff08;物理卷&#xff09;&#xff0c;使用pvcreate 命令 pvcreate /dev/sdc 或则是 pvcreate /dev/sdc /dev/sdb pvdisplay 或pvs 命令查看 PV 物理卷得创建情况 2,创建卷组 VG 通过vgcreate 命令,将pv加…

《图解TCP/IP》阅读笔记(第六章 6.3、6.4)—— 鼎鼎大名的UDP、TCP

前言&#xff1a; 本篇将要介绍UDP和TCP&#xff0c;篇幅略长&#xff0c;主要是TCP的内容较为复杂 6.3 UDP UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09; 根据此前的了解&#xff0c;UDP不提供复杂的控制机制&#xff0c;其是一种利用IP提…

JavaSE(类和对象、this用法、构造方法)

1. 面向对象 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 JAVA是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间的交互完成。 面向过程注重的是…