文章目录
- Leecode
-
- 2:两数相加
- 7:整数反转
- 9:回文数(不转换成字符串)
- 13:罗马数字转整数
- 15:三数之和
- 18:四数之和
- 19:删除链表的倒数第 N 个结点
- 20:有效的括号
- 21:合并两个有序链表
- 26:删除有序数组中的重复项
- 27:移除元素
- 28:实现strStr()
- 35:搜索插入位置
- 45:跳跃游戏 II
- 53:最大子序和
- 55:跳跃游戏
- 58:最后一个单词长度
- 66:加一
- 69:x的平方根
- 81:搜索旋转排序数组 II
- 100:相同的数
- 121:买卖股票的最佳时机
- 146:LRU缓存机制
- 168:Excel表列名称
- 169:多数元素
- 171:Excel表列序号
- 199:二叉树的右视图
- 230:二叉搜索树的最近公共祖先
- 240:搜索二维矩阵 II
- 258:各位相加
- 283:移动零
- 343:整数拆分
- 404:左叶子之和
- 461:汉明距离
- 485:最大连续1的个数
- 617:合并二叉树
- 802:找到最终的安全状态
- 876:链表的中间节点
- 961:重复N次的元素
- 1323:6和9组成的最大数字
- 1351:统计有序矩阵中的负数
- 1394:找出数组中的幸运数
- 1418:点菜展示表
- 1488:避免洪水泛滥
- 1480:一维数组的动态和
- 1711:大餐计数
- 1736:替换隐藏数字得到的最晚时间
- 1877:数组中最大数对和的最小值
- 1893:检查是否区域内所有整数都被覆盖
声明:题、图源自Leecode:https://leetcode-cn.com/
Leecode
2:两数相加
原题:https://leetcode-cn.com/problems/add-two-numbers/
提示:要注意两个链表长度不一的情况
注意用例 [2,4,9] [5,6,4,9] 和 [9,9,9,9] [9,9,9,9,9,9,9,9]
解答1:利用新链表存储结果,超出时间限制。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if(l1 == null && l2 == null) {
return null;
}
// l1和l2可能长度不同
int sign=0; // 进位
ListNode result=new ListNode(); // 结果链表
ListNode p=result;
// l1和l2相加
while(l1 != null && l2 != null) {
p=p.next=new ListNode();
int sum=l1.val+l2.val+sign;
// 有进位
if(sum>9) {
sign=1;
sum-=10;
}else {
sign=0;
}
p.val=sum;
l1=l1.next;
l2=l2.next;
}
// l1为空
while(l2 != null) {
p=p.next=new ListNode();
p.val=l2.val;
}
// l2为空
while(l1 != null) {
p=p.next=new ListNode();
p.val=l1.val;
}
return result.next;
}
}
解答2:运行时间 8 ms,内存消耗 39.1 MB
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if(l1 == null && l2 == null) {
return null;
}
ListNode result=l1;
ListNode p1=l1,p2=l2;
// 创建新链表会超出内存限制,因此采用原链表数据进行修改
int sign=0; // 进位
int sum=0;
while(l1 != null && l2 != null) {
sum=l1.val+l2.val+sign;
if(sum>9) {
sum-=10;
sign=1;
} else {
sign=0;
}
// 更新l1中的值为和
l1.val=sum;
p1=l1;p2=l2;
l1=l1.next;
l2=l2.next;
}
// 后面用于判断是否需要拼接l1与l2
boolean flag=false;
//ListNode temp=flag?l2:null;
ListNode temp=l2;
// l2不为空
while(l2 != null) {
flag=true;
// 有进位:更新值
if(sign == 1){
sum=l2.val+sign;
sign=sum>9?1:0;
l2.val=(sign==1)?sum-=10:sum;
}
// 指向当前的上一个
p2=l2;
l2=l2.next;
System.out.println(p2.val+",");
}
// l1不为空,且有进位:更新值
while(l1 != null) {
if(sign == 1) {
sum=l1.val+sign;
sign=sum>9?1:0;
l1.val=(sign==1)?sum-=10:sum;
}
// 指向当前的上一个
p1=l1;
l1=l1.next;
}
// 进位,但已经超出原来的长度
if(sign == 1){
ListNode last=flag?p2:p1;
last.next=new ListNode(1);
}
if(flag) {
// temp是链表2多出的部分
p1.next=temp;
}
return result;
}
}
7:整数反转
题目:
解法:运行时间 34 ms,内存消耗 38.5 MB
class Solution {
public int reverse(int x) {
if(x==0){
return 0;
}
String a=Integer.toString(x);
int length=a.length();
String result=""; //存放结果
int save=0;
int i=1;
if(x>0){ //x为正数
for(int j=0;j<length;i=i*10,j++){
if(j==length-1){
save=x/i;
result=result+save;
}else{
save=(x%(i*10))/i;
result=result+save;
}
}
try{ //溢出
save=Integer.parseInt(result);
}catch(Exception e){
return 0;
}
return save;
}
//当x<0,即x为负数的时候
i=1;
x=Math.abs(x); //将x转换为正数
for(int j=0;j<length-1;i=i*10,j++){
if(j==length-2){
save=x/i;
result=result+save;
}else{
save=(x%(i*10))/i;
result=result+save;
}
}
try{ //溢出
save=Integer.parseInt(result);
}catch(Exception e){
return 0;
}
return 0-save;
}
}
9:回文数(不转换成字符串)
题目:
解题:执行用时 20 ms ; 内存消耗 37.8 MB。
class Solution {
public boolean isPalindrome(int x) {
if(x<0){
return false;
}
if(x>=0&&x<10){
return true;
}
String s=x+"";
int length=s.length();
int j=1;int left;int right;int wei;
for(int i=0;i<length/2;i++,j=j*10){
wei=length-i;
left=x%(int)(Math.pow(10,wei))/(int)(Math.pow(10,wei-1));
right=x%(j*10)/j;
if(left==right){
continue;
}else{
return false;
}
}
return true;
}
}
13:罗马数字转整数
题目:
解题:执行用时 5 ms,内存消耗 38.4 MB。
class Solution {
public int romanToInt(String s) {
char c[]=s.toCharArray(); //将字符串s转换成字符数组
int k[]=new int[c.length]; //存放每个字符对应的数值
for(int i=0;i<c.length;i++){
switch(c[i]){
case 'I':k[i]=1;break;
case 'V':k[i]=5;break;
case 'X':k[i]=10;break;
case 'L':k[i]=50;break;
case 'C':k[i]=100;break;
case 'D':k[i]=500;break;
case 'M':k[i]=1000;break;
}
}
int sum=0; //存储计算结果
//计算输入的值
for(int i=0;i<c.length;i++){
if(i==c.length-1){ //当前是最后一个字符
sum=sum+k[i];
}else{
if(k[i]>=k[i+1]){ //正常情况,直接相加即可
sum=sum+k[i];
}else{ //特殊:小的数字在大的数字左边
sum=sum-k[i];
}
}
}
return sum;
}
}
15:三数之和
题目:给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
提示:注意用例 [0,0,0] [0,0,0,0] [-1,0,1,0]
解答:双指针法。执行用时 1719 ms,内存消耗 42.2 MB。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result=new ArrayList<>();
if(nums.length<3) return result;
// 排序,为了和结果顺序匹配
Arrays.sort(nums);
for(int i=0;i<nums.length && nums[i] <= 0;i++){
// 该值已经比对过一次
if(i>0 && nums[i] == nums[i-1]) {
continue;
}
for(int j=i+1;j<nums.length;j++){
int k=k=nums.length-1;
// j与上一个值相等:跳过该数
if(j>i+1 && nums[j] == nums[j-1]){
continue;
}
// 三个数之和大于0,k向前移动
while(j<k && (nums[i]+nums[j]+nums[k])>0){
k--;
// 若k重复,再向前
while(j < k && k != nums.length-1 && nums[k] == nums[k+1]){
k--;
}
}
if(j >= k){
break;
}
// 三个数之和=0,同时j和k没有重复指向同一个数
if((nums[i]+nums[j]+nums[k]) == 0){
List<Integer> current=new ArrayList<>();
current.add(nums[i]);
current.add(nums[j]);
current.add(nums[k]);
result.add(current);
}
}
}
return result;
}
}
18:四数之和
题目:给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:答案中不可以包含重复的四元组。
链接:https://leetcode-cn.com/problems/4sum
解答:执行用时 6 ms ; 内存消耗 38.5 MB。
参照三数之和的解法,利用双指针。首先数组排序,确定第一位和第二位,剩下两位用两个指针移动,若大于目标值则移动右指针;若小于目标值则移动左指针。
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res=new ArrayList<>();
if(nums == null || nums.length < 4) {
return res;
}
// 数组排序
Arrays.sort(nums);
for(int i=0;i<nums.length-3;i++) {
// 去除重复元素
if(i > 0 && nums[i] == nums[i-1]) {
continue;
}
// 若前四个数(当前数组中最小的值)相加大于目标值==>不存在结果集
if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3] > target) {
break;
}
// 若当前值+最大的三个数小于目标值==>当前值不存在符合的结果集
if(nums[i]+nums[nums.length-3]+nums[nums.length-2]+nums[nums.length-1] < target) {
continue;
}
for(int j=i+1;j<nums.length-2;j++) {
// 在本层循环:若上一个元素值与当前值相同,说明寻找过,跳过
if(j > i+1 && nums[j] == nums[j-1]) {
continue;
}
// 若当前元素i+j+最大的两位数小于目标值==>当前j不存在符合的结果集
if(nums[i]+nums[j]+nums[nums.length-1]+nums[nums.length-2] < target) {
continue;
}
// 若当前元素i+j+最小的两位大于目标值==>当前循环不存在结果
if(nums[i]+nums[j]+nums[j+1]+nums[j+2] > target) {
break;
}
int k=j+1;
int z=nums.length-1;
while(k<z) {
int sum=nums[i]+nums[j]+nums[k]+nums[z];
if(sum == target) {
// 加入结果中
List<Integer> cur=new ArrayList<>();
cur.add(nums[i]);
cur.add(nums[j]);
cur.add(nums[k]);
cur.add(nums[z]);
res.add(cur);
// 去重
while(k<z && nums[k] == nums[k+1]) {
k++;
}
// 跳出循环的时候:下一个k才是与当前不重复的,之前都是重复的
k++;
while(k<z && nums[z] == nums[z-1]) {
z--;
}
z--;
}else if(sum > target) {
// 当前值大于目标值,应该减小:当前z最大,移动z
z--;
}else if(sum < target) {
// 当前值小于目标值,应该增大:当前z最大,移动k
k++;
}
}
}
}
return res;
}
19:删除链表的倒数第 N 个结点
题目
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
提示:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
通过次数363,684提交次
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
解题
public ListNode removeNthFromEnd(ListNode head, int n) {
//创建一个链表指向head,多了一个头结点是0。保证当删除头结点时也可以正常删除。
ListNode copy=new ListNode(0,head);
//一个指针p1指向头结点
ListNode p1=copy;
//一个指针p2指向与p1相距n个节点的结点,即最后p1会指向要删除结点的上一位。
ListNode p2=head;
for(int i=0;i<n;++i){
//p2向后移n-1次
p2=p2.next;
}
//循环遍历,直到p2指向null(即p2上一位是尾结点)
while(p2!=null){
//p1,p2每次向后移一位
p1=p1.next;
p2=p2.next;
}
//此时p1指向的是倒数第n个节点的上一个节点
//删除第n个节点
p1.next=p1.next.next;
//去除头节点0
return copy.next;
}
20:有效的括号
题目:
解法:执行用时8ms,内存消耗36.7MB
class Solution {
public boolean isValid(Str