LeetCode 180, 68, 146

目录

  • 180. 连续出现的数字
    • 题目链接
    • 要求
    • 知识点
    • 思路
    • 代码
  • 68. 文本左右对齐
    • 题目链接
    • 标签
    • 思路
    • 代码
  • 146. LRU 缓存
    • 题目链接
    • 标签
    • 思路
    • 代码

180. 连续出现的数字

题目链接

180. 连续出现的数字

  • Logs的字段为idnum

要求

  • 找出所有 至少连续出现三次 的数字。
  • 返回的结果表中的数据可以按 任意顺序 排列。

知识点

  1. distinct:对某个字段进行去重。

思路

可以想到使用三个表来做多表查询,第一个表first查数字在三次出现中的第一次出现的id,第二个表second查第二次出现的id,第三个表third查数字在三次出现中的第三次出现的id,只要满足first.id = second.id - 1 and second.id = third.id - 1即可。

另外,因为是多表查询,所以要使用条件first.num = second.num and second.num = third.sum限制,防止产生无效数据。

最后,也是最关键的一点:如果一个num连续出现三次以上,则按照上面这种判断将会把这个num输出多次,故需要对num进行去重

代码

selectdistinct first.num ConsecutiveNums
fromLogs first,Logs second,Logs third
wherefirst.id = second.id - 1
andsecond.id = third.id - 1
andfirst.num = second.num
andsecond.num = third.num

68. 文本左右对齐

题目链接

68. 文本左右对齐

标签

数组 字符串 模拟

思路

有时候“困难”并不困难。就好比本题,只是解题的步骤多了点,而不是很难想。

题目中明确地说了要使用 贪心 的思想,即 通过局部最优解退出全局最优解 的思想,所以处理一行单词时不需要考虑上一行或下一行,只需要考虑如何让本行的单词数最多。这很简单,假设本行的单词之间只间隔一个空格,然后从文本中获取单词拼接即可。不过不能直接按一个空格的间隔拼接这些单词,因为间隔一个空格只是假设,实际情况可能不满足(即可能出现 结果中这行的每个单词需要间隔一个以上空格 的情况),所以得先获取这行拼接的所有单词的长度总和,然后再计算每个单词之间的平均间隔,如果间隔不平均,则需要将这些不平均的空格分散到左边的每个单词后。

对于最后一行,需要特殊处理:使用一个空格将最后一行的每个单词拼接起来,然后用空格填满最后一行的剩余部分,最后将结果返回。

对于每行只有一个单词的情况,也需要特殊处理:将这个单词左对齐,即用空格填充这行的右部分。

废话不多说,请看代码中的注释。

代码

class Solution {public List<String> fullJustify(String[] words, int maxWidth) {int n = words.length;List<String> res = new ArrayList<>();int right = 0; // right是每行已经拼接字符串的结尾单词的下标+1while (true) {int left = right; // left是每行起始单词的下标int sumLen = 0; // sumLen是这行的长度,不包括空格// 先计算出这行最多能放多少个单词// right - left 恰好是单词之间至少间隔的空格数,包含 已拼接的最后一个单词 与 待拼接单词 的空格// sumLen + words[right].length() + right - left 是这行已经填充的字符数// 如果right == n,说明单词已经放完了,就不需要再计算了while (right < n && sumLen + words[right].length() + right - left <= maxWidth) {sumLen += words[right++].length(); // 让sumLen加上这个单词的长度}// 如果right == n,拼接最后一行的字符串,将结果返回即可if (right == n) {StringBuilder builder = join(words, left, n, " "); // 用单个空格将这行单词拼接起来builder.append(blank(maxWidth - builder.length())); // 用空格填充最后一行的剩余部分res.add(builder.toString()); // 将最后一行字符串加入结果return res; // 返回结果}// 如果到这里了,说明不是最后一行int numWords = right - left; // right - left 可以表示这行拼接的单词数int numSpaces = maxWidth - sumLen; // numSpaces 是这行的空格数// 如果这行只有一个单词,那么直接将这个单词左对齐,看示例2的acknowledgment,它就是左对齐的if (numWords == 1) {StringBuilder builder = new StringBuilder(words[left]);builder.append(blank(numSpaces)); // 用空格填充这行的剩余部分res.add(builder.toString());continue;}// 如果到这里了,说明这行有不止一个单词// numWords - 1 是这行单词之间的间隔数int avgSpaces = numSpaces / (numWords - 1); // avgSpaces 是这行平均的空格数int extraSpaces = numSpaces % (numWords - 1); // extraSpaces 是无法平均的空格数// 题目中说了 左侧放置的空格数要多于右侧的空格数,所以把 不平均的空格 分散到 左边的每个单词后。即使不平均的空格数为0,也可以按照如下逻辑处理StringBuilder builder = new StringBuilder();builder.append(join(words, left, left + extraSpaces + 1, blank(avgSpaces + 1))); // 把不平均的空格分散到左边的每个单词后builder.append(blank(avgSpaces)); // 从这里开始空格就平均了,放 avgSpaces 个builder.append(join(words, left + extraSpaces + 1, right, blank(avgSpaces))); // 把平均的空格分散到右边的每个单词后res.add(builder.toString());}}// 构造n个空格的字符串private String blank(int n) {StringBuilder builder = new StringBuilder();while (n-- > 0) {builder.append(' ');}return builder.toString();}// 将 words中 索引在[left, right)这个左闭右开区间内的字符串 使用 interval 作为间隔 拼接起来private StringBuilder join(String[] words, int left, int right, String interval) {StringBuilder builder = new StringBuilder(words[left++]); // 先拼接一个字符串,再拼接间隔while (left < right) {builder.append(interval);builder.append(words[left++]);}return builder;}
}

146. LRU 缓存

题目链接

146. LRU 缓存

标签

设计 哈希表 链表 双向链表

思路

本题是一个设计题,要求设计一个数据结构,它具有这样的性质:

  • 如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字
  • 函数 getput 必须以 O ( 1 ) O(1) O(1) 的平均时间复杂度运行。

保证逐出最久的关键字很简单,使用队列即可。

但还要保证这个关键字是最久未使用的就比较麻烦了,其实还可以使用队列,不过在每次使用关键字时得把它放到队列的尾部。

但是如何把它放到队列尾部呢?实际上,把一个队列中的一个节点放到尾部可以先删除这个节点,再将其加入队列。

问题来了,如何以 O ( 1 ) O(1) O(1) 的平均时间复杂度 查询 和 删除 队列中的某一个节点呢?可以使用Map来映射,key为关键字,value为这个关键字在队列中的节点,在创建节点时就建立关键字与节点的映射,然后在查询和删除时使用关键字查出节点,接着就可以进行操作了。

要想以 O ( 1 ) O(1) O(1) 的平均时间复杂度删除队列中的某一个节点,需要将队列中的节点设置为双向节点,即这个节点即有指向后一个节点的指针,也有指向前一个节点的指针。另外,为了避免对删除头节点和尾节点的判断,可以使用带哨兵节点的双向循环链表,即链表的头部和尾部都指向一个哨兵节点,这样在删除的时候直接 让前一个节点的后指针指向后一个节点、让后一个节点的前指针指向前一个节点 即可,如果没有带哨兵节点,则在 删除节点是头节点或尾节点 时,还需要让链表的头节点或尾节点重新指向另一个节点。

代码更好理解一点,请看代码。

代码

class LRUCache {private static class Node {int key;int value;Node prev;Node next;public Node() {}public Node(int key, int value) {this.key = key;this.value = value;}}private static class DoublyLinkedList {Node head;Node tail;public DoublyLinkedList() {head = tail = new Node(); // 哨兵节点head.next = tail; // 头哨兵节点的后指针指向尾哨兵节点tail.prev = head; // 尾哨兵节点的前指针指向头哨兵节点}// 将新节点添加到尾部public void addLast(Node newLast) {Node oldLast = tail.prev; // 原来的尾节点newLast.prev = oldLast; // 让新节点的前指针指向原来的尾节点newLast.next = tail; // 让新节点的后指针指向尾哨兵节点tail.prev = newLast; // 让尾哨兵节点的前指针指向新节点oldLast.next = newLast; // 让原来的尾节点的后指针指向新节点}// 将指定节点从队列中移除public void remove(Node node) {Node prev = node.prev; // 获取前一个节点Node next = node.next; // 获取后一个节点prev.next = next; // 让前一个节点的后指针指向后一个节点next.prev = prev; // 让后一个节点的前指针指向前一个节点}// 移除队列中的第一个节点public Node removeFirst() {Node first = head.next; // 获取头节点remove(first); // 将头节点从队列中移除return first; // 返回头节点}}private final HashMap<Integer, Node> map = new HashMap<>();private final DoublyLinkedList list = new DoublyLinkedList();private final int capacity; // 容量public LRUCache(int capacity) {this.capacity = capacity;}public int get(int key) {// 如果没有这个元素,则返回-1if (!map.containsKey(key)) {return -1;}Node node = update(key); // 将节点更新到队列尾部return node.value; // 然后返回节点的值}public void put(int key, int value) {if (map.containsKey(key)) { // 如果有这个关键字,做更新操作Node node = update(key); // 将节点更新到队列尾部node.value = value; // 然后更新节点的值} else { // 否则没有这个关键字,做新增操作Node node = new Node(key, value); // 构造新节点map.put(key, node); // 建立映射list.addLast(node); // 将新节点加入队列尾部if (map.size() > capacity) { // 如果数量超出限制,则移除队列中的头节点Node removed = list.removeFirst();map.remove(removed.key); // 删除这个关键字与节点的映射}}}// 先删除再添加到尾部,实现将节点更新到尾部的效果private Node update(int key) {Node node = map.get(key);list.remove(node);list.addLast(node);return node;}
}

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

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

相关文章

协议模糊测试——利用真实FTP协议通信流量构建协议状态机

1、介绍 在对有状态协议进行模糊测试时,为了实现更加深层次的测试,一般都会构建一个状态机,利用协议的状态来引导模糊测试。构建协议状态机可以手动构建,但这需要协议的大量专业知识。为了节省人力和时间,本文利用协议真实通信流量,自动构建协议状态机。本文以FTP协议为例…

Mysql启动报错:本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止

某天开机,发现Mysql被异常关闭,并且启动不起来,出这篇文章也是为了下次遇到类似问题,迅速解决(请细读文章,因为第二个方案才是主要方案) 第一个解决方案 我采用的第一个方法查“端口占用“问题(因为这是一篇博客所以我写的操作比较详细为了方便后面看这篇博客的人,我自…

如何在前端项目中用字体图标替换图片,方便减小打包体积和统一切换颜色

1.进入阿里妈妈矢量图标图库 地址&#xff1a;阿里妈妈矢量图 2.搜索自己想要的图标 3.添加自己想要的图标 4.把刚才选的图标&#xff0c;添加到自己要下载的项目 5.把项目下载到本地 6.引入iconfont.css 在div上增加对应的类名就可以啦 下载的所有类名都在下面的demo_index…

MySQL从5.7升级到8.0步骤及其问题

MySQL从5.7升级到8.0步骤及其问题 前言 本文源自微博客&#xff0c;且以获得授权&#xff0c;请尊重版权。 一、需求背景 Docker环境下&#xff0c;MySQL5.7升级到8.0&#xff0c;数据迁移时使用的是mysqldump方式迁移。 二、迁移步骤 数据备份&#xff1a; docker exec -i 1…

python-画三角形

[题目描述] 输入一个正整数n&#xff0c;请使用大写字母拼成一个这样的三角形图案&#xff08;参考样例输入输出&#xff09;&#xff1a;三角形图案的第1行有1个字母&#xff0c;第2行有2个字母&#xff0c;以此类推&#xff1b;在三角形图案中&#xff0c;由上至下、由左至右…

使用高德API计算两个地址的距离

要使用高德地图API来计算两个城市之间的距离&#xff0c;你需要首先在高德开放平台上注册并获取API密钥&#xff08;AK&#xff09;。以下是一个使用Java调用高德地图API来计算两个城市之间距离的示例代码。 步骤 1: 获取高德地图API密钥 访问高德开放平台&#xff08;https:…

GIS设计与开发课程设计(三)

环境&#xff1a;Windows10专业版 ArcGIS10.2 ArcEngine10.2 Visual Studio 2019 因每个人电脑版本和软件版本不同&#xff0c;运行的结果可能不同 系列文章&#xff1a; GIS设计与开发课程设计&#xff08;一&#xff09; GIS设计与开发课程设计&#xff08;二&#xff09;…

Apple Watch开发入门知识,还是很有必要的

随着现在 Apple 生态圈的发展&#xff0c;越来越多的 App 会把自己的简化版从 iOS 迁移至 WatchOS&#xff08;支付宝、微信、手Q、头条、QQ音乐、网易云音乐等等&#xff0c;都有Watch版App&#xff09;。官方开发文档&#xff1a;Setting up a watchOS project | Apple Devel…

学习Java中的日志系统设计与优化

学习Java中的日志系统设计与优化 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 引言 在Java应用程序中&#xff0c;日志系统是非常重要的组成部分&#xff…

力扣1539.第k个缺失的正整数

力扣1539.第k个缺失的正整数 占位运算 只要n<k &#xff0c;k;最终k就是结果 class Solution {public:int findKthPositive(vector<int>& arr, int k) {for(int n : arr){if(n < k) k ;else break;}return k;}};

神经网络学习3-卷积层

膨胀卷积&#xff0c;也被称为空洞卷积或扩张卷积&#xff0c;是一种特殊的卷积运算&#xff0c;它在标准卷积的基础上引入了一个额外的超参数&#xff0c;即膨胀率&#xff08;dilation rate&#xff09;。这个超参数决定了在卷积核的元素之间插入多少额外的空间。通过这种方式…

04-对原生app应用中的元素进行定位

本文介绍对于安卓原生app应用中的元素如何进行定位。 一、uiautomatorviewer uiautomatorviewer是Android-SDK自带的一个元素定位工具&#xff0c;非常简单好用&#xff0c;可以使用该工具查看app应用中的元素属性&#xff0c;帮助我们在代码中进行元素定位。 1&#xff09;使…

为什么要用较短的域名?

在互联网的世界中&#xff0c;域名是网站身份的重要标识。一个好记、易于输入的域名对于网站的成功至关重要。在众多域名中&#xff0c;较短的域名因其独特的优势而受到青睐。本文将探讨为什么要选择较短的域名&#xff0c;并分析其带来的益处。 易记性 优势&#xff1a;较短…

黑龙江游戏行业需不需要做等保?

游戏行业是否需要进行等保 游戏行业作为当今最受欢迎的娱乐方式之一&#xff0c;其用户数量庞大且用户粘性强&#xff0c;因此成为了网络安全攻击的重点目标。为了保障游戏行业的网络安全&#xff0c;等级保护制度&#xff08;简称“等保”&#xff09;的实施显得尤为重要。 …

el-table 固定前n行 配合 max-height 生效

:row-class-name"TableRowClassName" 加上类名 <el-table:data"computedTableList"borderstyle"width: 100%":row-class-name"TableRowClassName"max-height"800"><el-table-column fixed prop"name"…

【OS基础】符合AUTOSAR标准的RTAOS-Alarms详解

目录 前言 正文 7.报警Alarms 7.1配置Alarms 7.1.1激活一个任务 7.1.2 设置一个事件 7.1.3报警回调Alarm Callback 7.1.4 增加计数器值 7.2设置Alarms 7.2.1 绝对Alarms 7.2.2 相对Alarm 7.3自启动Alarms 7.4 删除Alarms 7.5确认何时会发生Alarm 7.6非周期Alarm…

CC攻击需要成本吗

CC攻击几乎不需要成本。这是因为CC攻击很容易发起&#xff0c;大部分进行CC攻击的人都是使用在网上下载的工具&#xff0c;这些工具很少去伪造特征&#xff0c;因此会留下一些痕迹。这意味着&#xff0c;尽管CC攻击可能会对目标系统造成严重影响&#xff0c;但其发起者几乎不需…

Josephus问题

Josephus问题&#xff0c;又称为“约瑟夫环”或“丢手绢问题”&#xff0c;是一个经典的计算机科学和数学问题。这个问题的起源有一个古老的故事背景&#xff0c;但与解决问题的具体算法设计并无直接关联。以下是Josephus问题的详细描述和一种可能的解决方案&#xff1a; ### …

细致解析跨境电商多平台搭建利器-179海关接口源码应用方法

介绍 跨境电商已成为当前电商行业的热门发展方向之一。为满足跨境电商的需求&#xff0c;各大平台纷纷推出了多平台搭建利器。其中&#xff0c;179海关接口源码是一款非常实用的工具&#xff0c;本文将对其应用方法进行细致解析。 了解179海关接口源码 179海关接口源码可以帮…

Vue插件开发:Vue.js的插件架构允许开发者扩展Vue的核心功能,我们可以探讨如何开发一个Vue插件并与社区分享

了解Vue插件 Vue插件的概念: Vue插件用于为Vue.js添加全局级别的功能。它提供了一种开箱即用的机制来应用全局性的功能扩展。这些插件通常用来将全局方法或属性,组件选项,Vue实例的方法,或者注入一些组件选项比如mixins和自定义方法添加至Vue.js。 Vue插件的使用场景:…