一、简单题目合集
1、反转链表
题目:
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
思路:
- 设置一个前置节点pre以及当前需要反转的节点cur
- 将当前需要反转的cur节点的指针next指向pre
- 将已经反转的节点设置为pre,同时将cur继续后移,继续处理
- 循环直到cur为空 代码:
class Solution {
public ListNode reverseList(ListNode head) {
//1、创建一个用于移动的节点
ListNode pre = null;
//2、记录当前节点(当前需要处理的节点,下面是每个节点单独处理的)
ListNode current = head;
while(current != null){
//3、记录当前节点的下一个节点(因为当前节点处理完指针已经指向pre了,需要先存储下一个需要处理的节点)
ListNode tmp = current.next;
//4、修改当前节点的指针到前一个
current.next = pre;
//5、指针指向修改后,把自己作为目标节点让后面指向自己
pre = current;
//6、将当前需要处理的节点设置为下一个节点
current = tmp;
}
//7、返回当前最后一个节点(已经更换为头节点)
return pre;
}
}
2、合并两个有序链表
题目: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
思路: 注意关键点:有序 如果是两个链表或者数组合并,第一时间要想到递归!!!
代码:
lass Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 == null){
return list2;
}
if (list2 == null){
return list1;
}
if (list1.val < list2.val){
list1.next = mergeTwoLists(list1.next,list2);
return list1;
}else{
list2.next = mergeTwoLists(list1,list2.next);
return list2;
}
}
}
3、最大子数组和
题目
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 :
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
思路
核心思路:动态规划
动态规划有5个步骤:
- (1)设置一个dp[]的数组,思考当前i以及dp[i]的含义是什么
- (2)找到可循环的规律,公式
- (3)初始化数组:其实就是初始化一个或者两个规律上的初始值
- (4)写循环
- (5)打印dp[]数组,看下是否符合要求
根据动态规划的5个步骤,求最大的连续子数组的和可以这么思考:
-(1)dp[]数组中,i是当前的下标,dp[i]代表当前下标的最大和 -(2)这道题可以转换一个思路,类似有a b c 三个人,从a开始,a可能负债可能有钱,a找到b,b看了下a+b的钱还不如自己,那就自己重新开始往后找,b找到了c,发现b+c > b ,那么就保留b开始,同时计算最大的值是b+c
代码
class Solution {
public static int maxSubArray(int[] nums) {
//如果是空数组直接返回0
if (nums == null || nums.length == 0){
return 0;
}
//1、定义一个数组,数组的每个值是记录当前下标下最高的值
int [] dp = new int[nums.length];
//2、初始化第一个值为最大的结果
dp[0] = nums[0];
int result = nums[0];
//3、进行比较,如果前面的和小于当前的值,则放弃前面的和重新开始
for(int i = 1;i < nums.length;i++){
dp[i] = Math.max(dp[i-1] + nums[i],nums[i]);
result = Math.max(dp[i],result);
}
return result;
}
}
4、二分查找
题目
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
思路
class Solution {
public int search(int[] nums, int target) {
if (nums == null || nums.length ==0){
return -1;
}
int left = 0,right = nums.length -1;
while (left <= right){
//注意 核心在这里 需要注意中间的角标是怎么算出来的
int middle = left + (right - left)/2;
int compare = nums[middle];
if (compare == target){
return middle;
}else if (compare > target){
right = middle -1;
}else {
left = middle +1;
}
}
return -1;
}
}
5、234. 回文链表
题目
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例 1:
输入:head = [1,2,2,1]
输出:true
示例 2:
输入:head = [1,2]
输出:false
思路
核心思路是利用栈的思想(回文都可以考虑下用栈或者反转链表的方式来做)
代码
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null){
return false;
}
ListNode current = head;
//先计算长度并且把数据入栈
int length = 0;
Stack<Integer> stack = new Stack();
while(current != null){
stack.push(current.val);
current = current.next;
length ++;
}
boolean flag = true;
//数据出栈,对比数据是否完全一致,如果发现不一致,则不是回文
while(!stack.isEmpty()){
int value = stack.pop();
int val = head.val;
head = head.next;
if(value != val){
flag = false;
break;
}
}
return flag;
}
}
6、 141. 环形链表
题目
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
思路
判断是否有环的核心方式是快慢指针,如果有环,一个快一个慢,一定会相遇
代码
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null||head.next == null){
return false;
}
ListNode fast = head;
ListNode slow = head;
boolean flag = false;
while(fast!= null && fast.next !=null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
flag = true;
break;
}
}
return flag;
}
}
7、70. 爬楼梯
题目
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
思路
这也是找规律,根据大的拆成小的动态规划的题目
代码
class Solution {
public int climbStairs(int n) {
if (n <= 1){
return 1;
}
int d1 = 1;
int d2 = 1;
for (int i = 2;i<= n;i++){
int tmp = d2;
d2 = d1+d2;
d1 = tmp;
}
return d2;
}
}
8、160. 相交链表
题目
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
思路
判断是否相交的核心思路是两个指针走过的路是一模一样的。 只要两个人走的路径加起来一样,速度一样,那么一定会在某个时间点相遇。
代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null){
return null;
}
ListNode currentA = headA;
ListNode currentB = headB;
while(currentA != currentB){
currentA = currentA == null?headB:currentA.next;
currentB = currentB == null?headA:currentB.next;
}
return currentA;
}
}
9、121. 买卖股票的最佳时机
题目
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
示例 1:
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
思路
如果看到一串数组,寻找最大值,最小值,连续最大和等关键字,毫无疑问用动态规划。
- 分析当前价格与后面的价格开始的优势,如果没有优势,则用后面的重新开始。
- 在内存中维护一个最大值
代码
class Solution {
public int maxProfit(int[] prices) {
if(prices == null || prices.length == 0){
return 0;
}
//设置初始成本
int currentCost = prices[0];
//设置初始利润
int currentMoney = 0;
//设置最大利润
int maxProfit = 0;
for(int i = 1;i < prices.length;i++){
//设置当前比较的成本差
int compareCost = prices[i] - currentCost;
//如果亏钱 还不如重新开始设置当前值为成本价
if(compareCost <0){
currentCost = prices[i];
}
maxProfit = Math.max(maxProfit,compareCost);
}
return maxProfit;
}
}
9、剑指 Offer 22. 链表中倒数第k个节点
题目
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
思路 先计算长度,算出倒数第k个的位置是length -k,遍历就可以得到 代码
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
if(head == null){
return null;
}
//计算长度
ListNode cur = head;
int length = 0;
while(cur != null){
cur = cur.next;
length ++;
}
//锁定对应的地址 直接循环到最后的地址 取最后一个
for (int i=0;i < length -k;i++){
head = head.next;
}
return head;
}
}
10、232. 用栈实现队列
题目
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾 int pop() 从队列的开头移除并返回元素 int peek() 返回队列开头的元素 boolean empty() 如果队列为空,返回 true ;否则,返回 false 说明:
你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
代码
class MyQueue {
Stack<Integer> s1;
Stack<Integer> s2;
public MyQueue() {
s1 = new Stack();
s2 = new Stack();
}
public void push(int x) {
s1.push(x);
}
public int pop() {
if(s2.isEmpty()){
while(!s1.isEmpty()){
s2.push(s1.pop());
}
}
return s2.pop();
}
public int peek() {
if(s2.isEmpty()){
while(!s1.isEmpty()){
s2.push(s1.pop());
}
}
return s2.peek();
}
public boolean empty() {
return s1.isEmpty()&&s2.isEmpty();
}
}
11、9. 回文数
题目
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
示例 1:
输入:x = 121 输出:true 示例 2:
输入:x = -121 输出:false 解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。 示例 3:
输入:x = 10 输出:false 解释:从右向左读, 为 01 。因此它不是一个回文数。
思路
回文的题目核心一定要想到栈。
代码
class Solution {
//利用栈的思想判断回文数
public boolean isPalindrome(int x) {
boolean flag = true;
if(x <0){
return false;
}
String s = String.valueOf(x);
char[] array = s.toCharArray();
Stack<Character> stack = new Stack();
for (char a : array){
stack.push(a);
}
for (char a : array){
char c = stack.pop();
if (c != a){
flag = false;
break;
}
}
return flag;
}
}
12、876. 链表的中间结点
题目
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
代码
class Solution {
public ListNode middleNode(ListNode head) {
if(head == null){
return head;
}
int length = 0;
ListNode cur = head;
while(cur != null){
cur = cur.next;
length ++;
}
for (int i = 0;i< length/2;i++){
head = head.next;
}
return head;
}
}
13、83. 删除排序链表中的重复元素
题目
给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
示例 1:
输入:head = [1,1,2] 输出:[1,2]
思路
思路比较简单,移动指针到下一个即可
代码
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if (head == null){
return head;
}
ListNode cur = head;
while(cur != null && cur.next != null){
ListNode nextNode = cur.next;
if(cur.val == nextNode.val){
//注意这里是核心逻辑,如果相等,下一次比较还是当前节点的比较
cur.next = nextNode.next;
}else{
//如果不相等,当前节点的任务完成了
cur = nextNode;
}
}
return head;
}
}
13、415. 字符串相加
题目 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。
你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。
示例 1:
输入:num1 = "11", num2 = "123" 输出:"134"
思路
代码
class Solution {
public String addStrings(String num1, String num2) {
if (num1 == null){
return "";
}
if(num2 == null){
return "";
}
//先转数组
//从尾部开始加
//设置一个加的 通过对十取模
//循环到有一个的length <0 或者 逢10的那个加的为0
char[] array1 = num1.toCharArray();
char[] array2 = num2.toCharArray();
int length1 = array1.length -1 ;
int length2 = array2.length -1 ;
int addValue = 0;
StringBuilder sb = new StringBuilder();
while (length1 >=0 || length2 >= 0 || addValue >0){
int k1 = length1 < 0 ? 0 : array1[length1] -'0';
int k2 = length2 < 0 ? 0 :array2[length2] - '0';
int add = k1 + k2 + addValue;
sb.append(add%10);
addValue = add/10;
length1 --;
length2 --;
}
return sb.reverse().toString();
}
}
14、136. 只出现一次的数字
题目 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1] 输出: 1
思路 代码
class Solution {
public int singleNumber(int[] nums) {
List<Integer> list = new ArrayList<>();
for (int k : nums){
if(list.contains(k)){
list.remove(list.indexOf(k));
}else{
list.add(k);
}
}
return list.get(0);
}
}
15、9. 回文数
题目 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。
示例 1:
输入:x = 121 输出:true
思路 代码
class Solution {
//利用栈的思想判断回文数
public boolean isPalindrome(int x) {
if( x< 0){
return false;
}
String s = String.valueOf(x);
char[] array = s.toCharArray();
Stack<Character> characters = new Stack<>();
for (char a : array){
characters.add(a);
}
int index = 0;
while(!characters.isEmpty()){
char a = array[index];
index++;
if (characters.pop() != a){
return false;
}
}
return true;
}
}
16、125. 验证回文串
题目 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: "A man, a plan, a canal: Panama" 输出: true 解释:"amanaplanacanalpanama" 是回文串
代码
class Solution {
public boolean isPalindrome(String s) {
if(s == null){
return false;
}
char[] array = s.toCharArray();
StringBuilder sb1 = new StringBuilder();
for (Character a : array){
if(Character.isLetterOrDigit(a)){
sb1.append(Character.toLowerCase(a));
}
}
StringBuilder sb2 = new StringBuilder(sb1).reverse();
return sb2.toString().equals(sb1.toString());
}
}
17、 14. 最长公共前缀
题目
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入:strs = ["flower","flow","flight"] 输出:"fl"
代码
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs == null){
return "";
}
String answer = strs[0];
//遍历所有的字符串
for (int i = 1;i< strs.length;i++){
String tmp = strs[i];
int length = tmp.length();
int j= 0;
for (;j< length && j < answer.length();j++){
char init = answer.charAt(j);
char compare = tmp.charAt(j);
if(init != compare){
break;
}
}
answer = answer.substring(0,j);
if(answer == ""){
return "";
}
}
return answer;
}
}
18、459. 重复的子字符串
题目 给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
示例 1:
输入: s = "abab" 输出: true 解释: 可由子串 "ab" 重复两次构成。
思路
这道题的思路比较有趣,一个串的移动多少次之后都会在 s1 = s + s 里面包含,因此去掉第一位(还未旋转的),去掉最后一位(全部旋转的),再看看是否包含原来的字符串即可
代码
//https://leetcode-cn.com/problems/repeated-substring-pattern/solution/jian-dan-ming-liao-guan-yu-javaliang-xing-dai-ma-s/
//为什么要去掉头尾,头是旋转之前的,尾部是旋转之后的
class Solution {
public boolean repeatedSubstringPattern(String s) {
String str = s + s;
return str.substring(1,str.length()-1).contains(s);
}
}
19、26. 删除有序数组中的重复项
题目
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组 int[] expectedNums = [...]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length; for (int i = 0; i < k; i++) { assert nums[i] == expectedNums[i]; } 如果所有断言都通过,那么您的题解将被 通过。
示例 1:
输入:nums = [1,1,2] 输出:2, nums = [1,2,_] 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
思路
题目可以使用快慢指针,慢指针用来指向当前不重复数据的下标,快指针用于遍历,当快指针的数据等于快指针的前一个,则跳过,如果不相等,则放置到慢指针所在的位置
代码
// https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/solution/shan-chu-pai-xu-shu-zu-zhong-de-zhong-fu-tudo/
class Solution {
public int removeDuplicates(int[] nums) {
if(nums == null || nums.length == 1){
return 1;
}
int slow = 1;
int fast = 1;
for (int i = 1;i < nums.length;i++){
if (nums[fast] != nums[fast-1]){
nums[slow] = nums[fast];
slow ++;
fast ++;
}else{
fast ++;
}
}
return slow;
}
}
20、剑指 Offer 11. 旋转数组的最小数字
题目 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。
思路 二分查找,但是需要判定一下条件(看下是否数组找靠近中间的都可以考虑下二分)
代码
class Solution {
public int minArray(int[] numbers) {
int left = 0;
int right = numbers.length -1;
while (left < right){
int middle = left + (right - left)/2;
if(numbers[right] < numbers[middle]){
left = middle +1;
} else if (numbers[right] > numbers[middle]){
right = middle;
}else{
right = right -1;
}
}
return numbers[left];
}
}
20、20. 有效的括号
题目 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。
示例 1:
输入:s = "()" 输出:true 示例 2:
输入:s = "()[]{}" 输出:true
思路
其实就是利用栈的思想,在子串上,是一个类似回文子串,那就可以用栈 代码
class Solution {
public boolean isValid(String s) {
if(s == null){
return false;
}
Stack<Character> stack = new Stack<>();
char[] array = s.toCharArray();
for(char c : array){
if(stack.isEmpty()){
stack.push(c);
}else{
char top = stack.peek();
if((top == '(' && c == ')') || (top == '[' && c == ']')|| (top == '{' && c == '}')){
stack.pop();
}else{
stack.push(c);
}
}
}
return stack.isEmpty();
}
}
21、155. 最小栈
题目 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。 pop() —— 删除栈顶的元素。 top() —— 获取栈顶元素。 getMin() —— 检索栈中的最小元素。
思路
代码
class MinStack {
Stack<Integer> noraml ;
Stack<Integer> min ;
public MinStack() {
noraml = new Stack<>();
min = new Stack<>();
}
public void push(int val) {
noraml.push(val);
if(min.isEmpty()){
min.push(val);
}else{
int top = min.peek();
if (top >= val){
min.push(val);
}
}
}
public void pop() {
int value = noraml.pop();
int top = min.peek();
if(value <= top){
min.pop();
}
}
public int top() {
return noraml.peek();
}
public int getMin() {
return min.peek();
}
}
22、283. 移动零
题目 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12] 输出: [1,3,12,0,0]
思路 利用快慢指针,如果发现快指针不为0,则跟慢指针替换,替换后慢指针往前走。 整体替换完成后,要从慢指针往后开始改成0 代码
class Solution {
public void moveZeroes(int[] nums) {
int slow = 0;
int fast = 0;
int length = nums.length;
for (int i = 0;i < length;i++){
int slowValue = nums[slow];
int fastValue = nums[fast];
if(fastValue != 0){
nums[slow] = fastValue;
slow++;
}
fast++;
}
for (int i = slow;i< length ;i++){
nums[i] = 0;
}
}
}
23、剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
题目 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。
示例:
输入:nums = [1,2,3,4] 输出:[1,3,2,4] 注:[3,1,2,4] 也是正确的答案之一。
思路
双指针思路,比较左右两边的值是否需要替换。
代码
class Solution {
public void moveZeroes(int[] nums) {
int slow = 0;
int fast = 0;
int length = nums.length;
for (int i = 0;i < length;i++){
int slowValue = nums[slow];
int fastValue = nums[fast];
if(fastValue != 0){
nums[slow] = fastValue;
slow++;
}
fast++;
}
for (int i = slow;i< length ;i++){
nums[i] = 0;
}
}
}
24、7. 整数反转
题目 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 1:
输入:x = 123 输出:321
思路
代码有点问题的。。。
代码
class Solution {
public int reverse(int x) {
int result = 0;
while(x != 0 ){
int value = x % 10;
result = result * 10 + value;
x = x/10;
}
return result;
}
}
25、 349. 两个数组的交集
题目
给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2] 示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出:[9,4] 解释:[4,9] 也是可通过的
思路
代码
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> h1 = new HashSet<>();
HashSet<Integer> h2 = new HashSet<>();
HashSet<Integer> h3 = new HashSet<>();
for (int v : nums1){
h1.add(v);
}
for (int v : nums2){
h2.add(v);
}
Iterator<Integer> i1 = h1.iterator();
while(i1.hasNext()){
int val = i1.next();
if(h2.contains(val)){
h3.add(val);
}
}
int [] answer = new int [h3.size()];
int i = 0;
Iterator<Integer> i3 = h3.iterator();
while(i3.hasNext()){
int value = i3.next();
answer[i] = value;
i ++;
}
return answer;
}
}
26、1047. 删除字符串中的所有相邻重复项
题目 给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca" 输出:"ca"
代码
class Solution {
public String removeDuplicates(String s) {
if(s == null){
return "";
}
char[] array = s.toCharArray();
Stack<Character> stack = new Stack();
for (char value : array){
//如果栈开始就是空的 入栈
if(stack.isEmpty()){
stack.push(value);
}else{
//如果栈不是空的,比较栈顶跟即将入栈的值,如果相同,则出栈,如果不相同,则入栈
if(value == stack.peek()){
stack.pop();
}else{
stack.push(value);
}
}
}
StringBuilder sb = new StringBuilder();
while(!stack.isEmpty()){
sb.append(stack.pop());
}
return sb.reverse().toString();
}
}
题目 从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
输入: [0,0,1,2,5]
输出: True
输入: [1,2,3,4,5]
输出: True
思路
核心思路:比较最大值与最小值是否超过5,如果是则有2个大小王也没有办法凑成顺子,另外就是看是否有重复的,如果除了大小王还有重复的。注意下最小的值,不能写成0,应该写成>13的数字。
代码
class Solution {
public boolean isStraight(int[] nums) {
List<Integer> list = new ArrayList();
int max = 0;
int min = 14;
for(int i = 0;i< nums.length;i++){
int value = nums[i];
if (value == 0){
continue;
}
if(list.contains(value)){
return false;
}
list.add(value);
max = Math.max(value,max);
min = Math.min(value,min);
}
return max - min < 5;
}
}
28、344. 反转字符串
题目
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
示例 1:
输入:s = ["h","e","l","l","o"] 输出:["o","l","l","e","h"]
代码
class Solution {
public void reverseString(char[] s) {
int left = 0;
int right = s.length -1;
while (left < right){
char temp = s[left];
s[left] = s[right];
s[right] = temp;
left ++;
right --;
}
}
}
29、 1. 两数之和
题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
思路
代码
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> map = new HashMap();
for (int i = 0;i < nums.length;i++){
//计算差额
int compare = target - nums[i];
//如果差额在map中已经存在,则返回
boolean exist = map.get(compare) == null? false:true;
if(exist){
return new int[]{map.get(compare),i};
}else{
map.put(nums[i],i);
}
}
return new int[]{};
}
}
30、144. 二叉树的前序遍历
题目
给你二叉树的根节点 root ,返回它节点值的 前序 **遍历。
思路
本质上是把二叉树进行拆分,因为是中-左-右的思路,所以需要按照中、右、左的思路出栈。
代码
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList();
if(root == null){
return list;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while(!stack.isEmpty()){
//先加入头节点(先弹出的节点)
TreeNode node = stack.pop();
list.add(node.val);
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
}
return list;
}
}
31、268. 丢失的数字
题目
给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
示例 1:
输入:nums = [3,0,1] 输出:2 解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。
思路
代码
class Solution {
public int missingNumber(int[] nums) {
Set<Integer> set = new HashSet<>();
for (int num : nums){
set.add(num);
}
for (int i = 0;i < nums.length;i++){
int compare = nums.length - i;
if(!set.contains(compare)){
return compare;
}
}
return 0;
}
}
32、 557. 反转字符串中的单词 III
题目 给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
示例 1:
输入:s = "Let's take LeetCode contest" 输出:"s'teL ekat edoCteeL tsetnoc"
代码
class Solution {
public String reverseWords(String s) {
String [] array = s.split(" ");
StringBuilder sb = new StringBuilder();
for (int i = 0;i< array.length;i++){
char[] arr = array[i].toCharArray();
int left = 0;
int right = arr.length -1;
while(left < right){
char temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left ++;
right --;
}
for (char a : arr){
sb.append(a);
}
sb.append(" ");
}
return sb.substring(0,sb.length()-1).toString();
}
}
33、 94. 二叉树的中序遍历
题目
给定一个二叉树的根节点 root ,返回它的 中序 遍历。
思路
一直往左走,再往上走,再往右走。
代码
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList();
if(root == null){
return list;
}
TreeNode cur = root;
Stack<TreeNode> stack = new Stack();
while(!stack.isEmpty() || cur != null){
while(cur != null){
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
list.add(cur.val);
cur = cur.right;
}
return list;
}
}