Leedcode刷题记录及笔记
注:本篇为小白入门刷题日常记录,欢迎讨论与分享更好的刷题方法
栈与队列
问题1:剑指 Offer 09. 用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
示例 1:
输入:
[“CQueue”,“appendTail”,“deleteHead”,“deleteHead”]
[[],[3],[],[]]
输出:[null,null,3,-1]
示例 2:
输入:
[“CQueue”,“deleteHead”,“appendTail”,“appendTail”,“deleteHead”,“deleteHead”]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]
题目链接:剑指 Offer 09. 用两个栈实现队列
python代码如下:
class CQueue:
def __init__(self):
self.A, self.B = [], []
def appendTail(self, value:int) -> None:
self.A.append(value)
def deleteHead(self) -> int:
if self.B:return self.B.pop()
if not self.A: return -1
while self.A:
self.B.append(self.A.pop())
return self.B.pop()
字符串
问题1:剑指 Offer 05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = “We are happy.”
输出:“We%20are%20happy.”
题目链接:剑指 Offer 05. 替换空格
Python代码如下:
class Solution:
#-> str标记返回值的类型
def replaceSpace(self, s: str) -> str:
res = []
for c in s:
if c == ' ':res.append("%20")
else:res.append(c)
return "".join(res)
#在自己电脑上运行首先要将类实例化再调用
s = Solution()
x = input()
print(s.replaceSpace(x))
问题2:剑指 Offer 58 - II. 左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。
示例 1:
输入: s = “abcdefg”, k = 2
输出: “cdefgab”
示例 2:
输入: s = “lrloseumgh”, k = 6
输出: "umghlrlose
题目链接:剑指 Offer 58 - II. 左旋转字符串
第一种解法:直接切片
Python代码如下:
#直接切片
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
return s[n:] + s[0:n]
第二种解法:花式反转
Python代码如下:
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
#先把字符串挨个分开
s = list(s)
s[0:n] = list(reversed(s[0:n]))
s[n:] = list(reversed(s[n:]))
s.reverse()
#s = reversed(s)
#此时字符串还是挨个元素分开的,所以最后要用join函数整合成一个字符串
return "".join(s)
注:
上面两个反转函数一个是reverse(),一个是reversed()。
reverse()为列表内置方法,只能用于列表中数据反转。
reversed()为python自带方法类,可用于列表反转、元组反转、字符串反转,也就是说可以把上面的s.reverse()替换为s = reversed(s)也可以达到整体反转的目的
双指针问题
问题1:删除有序数组中的重复项
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
题目链接:26.删除有序数组中的重复项1
JAVA代码如下:
class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length == 0 || nums == null)
return 0;
int left = 0;
for(int right = 1; right < nums.length; right++)
if(nums[right] != nums[left])
nums[++left] = nums[right];
return ++left;
}
}
题中给出的数组是按顺序排列的,所以只需要看相邻的两个元素是否相同,如果不相同则将当前元素(left)的下一个元素与右面(right)的元素互换位置,最后排成前几个为不重复的顺序的数组。
注:
1、++a与a++的区别:++a为先加1再做运算/赋值,a++为先运算/赋值再加1。
2、时间复杂度的计算2
日期:2022.01.07
问题2:旋转数组
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
题目链接
用双指针,一个快指针一个慢指针,整成环形链表再断开。
首先把指针移动到数组最后一个值,把它的下一个与数组的第一个值链上,变成环形链表。
再算出移动几步的前一个步的位置(防止找不到该节点断开的位置)。因为它移动的步数可能比数组还长,所以用取余%。
最后在断开位置断开。
public ListNode rotateRight(ListNode head, int k) {
if (head == null)
return head;
ListNode fast = head, slow = head;
//链表的长度
int len = 1;
//统计链表的长度,顺便找到链表的尾结点
while (fast.next != null) {
len++;
fast = fast.next;
}
//首尾相连,先构成环
fast.next = head;
//慢指针移动的步数
int step = len - k % len;
//移动步数,这里大于1实际上是少移了一步
while (step-- > 1) {
slow = slow.next;
}
//temp就是需要返回的结点
ListNode temp = slow.next;
//因为链表是环形的,slow就相当于尾结点了,
//直接让他的next等于空
slow.next = null;
return temp;
}
作者:sdwwld
链接:https://leetcode-cn.com/problems/rotate-list/solution/shu-ju-jie-gou-he-suan-fa-shuang-zhi-zhe-u99o/
日期:2022.01.09
哈希表法
问题1:两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
题目链接:两数之和3
解法:先建立哈希表,挨个看数组里的值,用target-该值,从第二个数开始,如果做减法后的值在哈希表里没有,就把这个数写到哈希表里。
JAVA代码如下:
class Solution {
public int[] twoSum(int[] nums, int target) {
//建立哈希表,<>中写的是包装类。
//HashMap 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类。
//包括Boolean、Byte、Short、Integer、Long、Float、Double、Character
Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; i++) {
if (hashtable.containsKey(target - nums[i])) {
//containsKey() 方法检查 hashMap 中是否存在指定的 key 对应的映射关系。
//用法:hashmap.containsKey(Object key)
//访问元素:可以使用 get(key) 方法来获取 key 对应的 value:
return new int[]{hashtable.get(target - nums[i]), i};
}
//HashMap 类提供了很多有用的方法,添加键值对(key-value)可以使用 put() 方法:
hashtable.put(nums[i], i);
}
return new int[0];
}
}
日期:2022.01.08
动态规划
买卖股票的最佳时机Ⅱ
给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
题目链接4
动态规划 前i天的最大收益 = max{前i-1天的最大收益,第i天的价格-前i-1天中的最小价格}
贪心法 实际上这道题不考虑手续费,买卖不限次数,直接把价格上升的区间加和就行。
class Solution {
public int maxProfit(int[] prices) {
int ans = 0;
int n = prices.length;
for (int i = 1; i < n; ++i) {
ans += Math.max(0, prices[i] - prices[i - 1]);
}
return ans;
}
}
这与买卖股票的第一题不同处在
日期:2022.01.09