LeetCode中等题(二)
题目一:
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
分析:这是一道三元组求和问题
1、首先定义返回的元组类型,List<List<Integer>> ans=new ArrayList<>();
2、对刚开始的数组进行排序,Arrays.sort(nums);
3、通过一个指针遍历整个数组for(int i=0;i<num.lenght;i++)
4、再设置两个指针,分别是l=i+1,r=len-1;
5、接下来开始求和进行判断;if(nums[i]+nums[l]+nums[r]==0)将l++,r--;
6、当然应该存入到ans.add(Arrays.asList(nums[i],nums[l],nums[r]));
7、在这个过程可能产生重复,if(nums[i]>0) break,if(i>&&nums[i]==nums[i-1]) continue;while(nums[l]==nums[l+1]) l++; r同样;
8、如果和不同sum<0,l++;sum>0,r--;
9、返回ans;
具体代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> ans=new ArrayList<>();
int len=nums.length;
if(nums==null||len<3) return ans; Arrays.sort(nums); for(int i=0;i<len;i++)
{
int l=i+1,r=len-1;
if(nums[i]>0) break;
if(i>0&&nums[i]==nums[i-1]) continue;
while(l<r)
{
int sum=nums[i]+nums[l]+nums[r];
if(sum==0)
{
ans.add(Arrays.asList(nums[i],nums[l],nums[r]));
while(l<r&&nums[l]==nums[l+1]) l++;
while(l<r&&nums[r]==nums[r-1]) r--;
l++;
r--;
}
else if(sum<0) l++;
else if(sum>0) r--;
}
}
return ans;
}
}
题目二:
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
方法一:
1、首先产生所有括号的情况;
2、采用递归算法,先定义一个函数实现所有括号的情况,其等于‘(’+n-1的序列和‘)’+n-1的序列和
3、进行判断所产生的序列是否有效,设置一个balance=0,if(c=='(') balance++;否则balance--;
4、如果balance<0 返回false;
具体代码:
class Solution {
public List<String> generateParenthesis(int n) {
List<String> result=new ArrayList(); GenerateAll(new char[2*n],0,result);
return result;
} public void GenerateAll(char[] current,int pos,List<String> res)
{
if(current.length==pos)
{
if(Valid(current))
{
res.add(new String(current));
}
}
else {
current[pos]='(';
GenerateAll(current,pos+1,res);
current[pos]=')';
GenerateAll(current,pos+1,res);
}
} public boolean Valid(char[] current)
{
int balance=0;
for(char c:current)
{
if(c=='(') balance++;
else {
balance--;
} if(balance<0) return false;
} return (balance==0);
}
}
题目三:
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
输入: [1,8,6,2,5,4,8,3,7]
输出: 49
方法一:
1、采用暴力法,双循环遍历出所有的情况;
2、进行逐个比较取最大值,计算公式为数组最小值和两个数组值之间的距离进行相乘;
具体代码:
class Solution {
public int maxArea(int[] height) { int ans=0;
int result=0;
int minVal=0;
for(int i=0;i<height.length;i++)
for(int j=i+1;j<height.length;j++)
{
minVal=Math.min(height[i], height[j]);
result=minVal*(j-i);
ans=Math.max(ans, result);
} return ans;
}
}
方法二:
1、使用双指针,一个数组第一位开始,另一个从数组的最后一位开始;
2、保持数组最大值不动,移动最小的值;
具体代码:
class Solution {
public int maxArea(int[] height) { int p=0,q=height.length-1;
int ans=0;
int minVal=0;
int result=0; while(p<q)
{
int distance=q-p; minVal=Math.min(height[p], height[q])
if(height[p]<height[q])
{
minVal=height[p];
p++;
}
else {
minVal=height[q];
q--;
}
result=minVal*distance;
ans=Math.max(ans, result);
}
return ans;
}
}
题目四:
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
方法一:
1、递归实现,如果是两两反转递归应该是swapPairse(next.next);
2、head.next=swapPairse(next.next),next.next=head;
3、返回next:
4、递归一定要有递归出口,递归出口,递归出口,if(head==null||head.next==null) return head;
具体代码:
class Solution {
public ListNode swapPairs(ListNode head) { if(head==null||head.next==null)
return head; ListNode next=head.next;
head.next=swapPairs(next.next);
next.next=head; return next;
}
}
方法二:
非递归算法
具体代码:
class Solution {
public ListNode swapPairs(ListNode head) { ListNode dummy=new ListNode(0);
dummy.next=head; ListNode curr=dummy; while(curr.next!=null&&curr.next.next!=null)
{
ListNode start=curr.next;
ListNode end=curr.next.next;
curr.next=end;
start.next=end.next;
end.next=start;
curr=start;
}
return dummy.next;
}
}
题目五:
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
方法一:
1、现对原始数组排序,Arrays.sort(nums);
2、返回return nums[nums.leght-k],这种方式较为简单;
方法二:
1、使用大顶堆获取最大的k个数;
2、java中使用优先队列PriorityQueue类定义了最小堆的实现,PriorityQueue<Integer> heap=new PriorityQueue<>(),通过这个函数得到的是最小堆;
3、对数组元素进行遍历,for(i:nums) heap.add(i),值得注意的是当一个元素加入到堆当中,系统自动将最小的元素放到堆顶排序好;
4、if(heap.size()>k) heap.poll();将堆顶元素删除,并且又最后一个元素覆盖,再次进行建立最小堆;
5、最后得到k个元素的最小堆,因为本地要输出第k个大小的值,刚好输出堆顶元素;
具体代码:
class Solution {
public int findKthLargest(int[] nums, int k) { PriorityQueue<Integer> pQueue=new PriorityQueue<>();
for(int i:nums)
{
pQueue.add(i); if(pQueue.size()>k)
pQueue.poll();
} return pQueue.poll();
}
}
题目六:
具体代码:
public class Main{
public static long MaxProduct(int n,long[] arr)
{
long max1=0,max2=0,max3=0,min1=0,min2=0;
for(int i=0;i<n;i++)
{
if(arr[i]!=0)
{
if(arr[i]>max1)
{
max3=max2;
max2=max1;
max1=arr[i];
}
else if(arr[i]>max2)
{
max3=max2;
max2=arr[i];
}
else if(arr[i]>max3)
{
max3=arr[i];
}
else if(arr[i]<min1)
{
min2=min1;
min1=arr[i];
}
else if (arr[i]<min2) {
min2=arr[i];
}
}
else {
continue;
}
} return Math.max(max1*max2*max3,max1*min1*min2);
} public static void main(String[] arg)
{
Scanner input=new Scanner(System.in);
int n=input.nextInt();
long[] arr=new long[n];
for(int i=0;i<n;i++)
{
arr[i]=input.nextLong();
} System.out.println(MaxProduct(n,arr)); }
}
题目七:
有序数组进行查找目标元素
1、最简单查找
l=0,r=lengh-1,while(l<=r),左右值的变化都为l=mid+1,r=mid-1;
具体代码:
class Solution {
public static void main(String[] args)
{
int[] nums= {1,2,3,4,5};
int target=10; System.out.println(TwoDisv(nums,target));
} public static int TwoDisv(int[] nums,int target)
{
int l=0,r=nums.length-1; while(l<=r)
{
int mid=(l+r)/2;
if(nums[mid]==target)
return mid;
else if (nums[mid]<target) {
l=mid+1;
}
else if (nums[mid]>target) {
r=mid+1;
}
}
return -1;
}
}
2、查找目标值左边界
l=0,r=length,while(l<r),if(l<target) l=mid+1,if(r>target) r=mid;,因为这是一个左闭右开区间;
最关键的点在if(nums[mid]==target) 并不是直接的返回,而是r=mid,逐步向左移动,直到最左边;
具体代码:
class Solution {
public static void main(String[] args)
{
int[] nums= {1,2,3,3,5};
int target=3; System.out.println(TwoDisv(nums,target));
} public static int TwoDisv(int[] nums,int target)
{
int l=0,r=nums.length; while(l<r)
{
int mid=(l+r)/2;
if(nums[mid]==target)
r=mid;
else if (nums[mid]<target) {
l=mid+1;
}
else if (nums[mid]>target) {
r=mid;
}
}
return r;
}
}
3、查找目标元素的右边界
l=0,r=length,while(l<r) if(nums[mid]==target) l=mid-1,最后返回也需要修改return l-1;
具体代码:
class Solution {
public static void main(String[] args)
{
int[] nums= {1,2,3,3,3};
int target=3; System.out.println(TwoDisv(nums,target));
} public static int TwoDisv(int[] nums,int target)
{
int l=0,r=nums.length; while(l<r)
{
int mid=(l+r)/2;
if(nums[mid]==target)
l=mid+1;
else if (nums[mid]<target) {
l=mid+1;
}
else if (nums[mid]>target) {
r=mid;
}
}
return r-1;
}
}
4、得出左右集合代码:
class Solution {
public int[] searchRange(int[] nums, int target) { return new int[]{left(nums,target),right(nums,target)};
} public int left(int[] nums,int target)
{
int l=0,r=nums.length; while(l<r)
{
int mid=(l+r)/2;
if(nums[mid]==target)
{
r=mid;
}
else if (nums[mid]<target) {
l=mid+1;
}
else if (nums[mid]>target) {
r=mid;
}
} return r;
}
public int right(int[] nums,int target)
{
int l=0,r=nums.length; while(l<r)
{
int mid=(l+r)/2;
if(nums[mid]==target)
{
l=mid-1;
}
else if (nums[mid]<target) {
l=mid+1;
}
else if (nums[mid]>target) {
r=mid;
}
} return l-1;
}
}
题目八:
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
方法一:
1、整体思路是递归回溯进行求解,每次进行递归进行深度优先遍历,if(currSize==len) res.add(new ArrayList<>(path));
2、需要设置一个是否遍历过的数值,if(!visied[i]) path.push(nums[i]);
3、visied[i]=false,generePermuse(nums,currsize+1,res);
4、这一步进行较为重要,将栈的最后一位去除,path.pop(),visied[i]=true;
5、正是因为将数组最后一个元素删除,进而向上才能出现继续遍历其他可能的情况;
具体代码:
class Solution {
public List<List<Integer>> permute(int[] nums) { List<List<Integer>> res=new ArrayList<>();
int len=nums.length;
boolean[] used=new boolean[len]; GeregePremute(nums,used,0,len,new Stack<>(),res)
return res;
} public void GeregePremute(int[] nums,boolean[] visied,
int currSize,int len,Stack<Integer> path,List<List<Integer>> res)
{
if(currSize==len)
{
res.add(new ArrayList<>(path));
return;
} for(int i=0;i<nums.length;i++)
{
if(!visied[i])
{
path.push(nums[i]);
visied[i]=true;
GeregePremute(nums,visied,currSize+1,len,path,res);
path.pop();
visied[i]=false;
}
}
}
}
题目九:
给定一个 n × n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例 1:
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
方法一:
1、先对矩阵进行转置;
2、对转置后的矩阵的每一行进行反转,最前和最后进行交换;
具体代码:
class Solution {
public void rotate(int[][] matrix) { int len=matrix.length; for(int i=0;i<len;i++)
for(int j=i;j<len;j++)
{
int temp=matrix[j][i];
matrix[j][i]=matrix[i][j];
matrix[i][j]=temp;
} for(int i=0;i<len;i++)
for(int j=0;j<len/2;j++)
{
int temp=matrix[i][j];
matrix[i][j]=matrix[i][len-j-1];
matrix[i][len-j-1]=temp;
}
}
}
方法二:
1、矩阵旋转其实就是四个元素进行旋转,一直循环;
2、难点就是找到这四个元素,比如某元素为(i,j),其他元素为(n-j-1,i),(n-i-1,n-j-1),(j,n-i-1)将这四个元素进行互换;
3、这里的循环条件也不是很好理解,for(int i=0;i<n/2;i++) for(int j=j;j<n-j-1;j++)
具体代码:
class Solution {
public void rotate(int[][] matrix) { int n=matrix.length; for(int i=0;i<n/2;i++)
for(int j=i;j<n-i-1;j++)
{
int temp=matrix[i][j];
matrix[i][j]=matrix[n-j-1][i];
matrix[n-j-1][i]=matrix[n-i-1][n-j-1];
matrix[n-i-1][n-j-1]=matrix[j][n-i-1];
matrix[j][n-i-1]=temp;
}
}
}
题目十:
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
方法一:
1、递归法,求左上角到右下角的最小和,可以先走一步,求grid[i+1][j]和grid[i][j+1]的最小值;
2、从i=0,j=0开始递归;
3、需要重新递归函数,将遍历变量放入,递归出口为:if(i==grid.lengh&&j==grid[0].lenght) return Integer.MAX_VALUE;
4、if(i==grid.lenght-1&&j==grid[0].lenght-1) return grid[i][j];
具体代码:
class Solution {
public int caculate(int[][] grid, int i,int j)
{
if(i==grid.length||j==grid[0].length) return Integer.MAX_VALUE;
if(i==grid.length-1&&j==grid[0].length-1) return grid[i][j]; return grid[i][j]+Math.min(caculate(grid, i, j+1), caculate(grid, i+1, j));
}
public int minPathSum(int[][] grid) {
return caculate(grid,0,0);
}
}
方法二:
1、动态规划,dp[i][j]表示点(i,j) 到右下角的最短距离;
2、dp[i][j]=grid[i][j]+Math.min(dp[i+1][j],dp[i][j+1])动态方程;
3、初始化过程:if(i==grid.lenght&&j!=grid[0].lenght) dp[i][j]=grid[i][j]+dp[i][j+1];
4、if(i!=grid.lenght&&j==grid[0].lenght) dp[i][j]=grid[i][j]+dp[i+1][j];
5、否则为动态方程:dp[i][j]=grid[i][j]+Math.min(dp[i+1][j],dp[i][j+1])
6、最后为:else dp[i][j]=grid[i][j];
具体代码:
class Solution {
public int minPathSum(int[][] grid) { int[][] dp=new int[grid.length][grid[0].length]; for(int i=grid.length-1;i>=0;i--)
for(int j=grid[0].length-1;j>=0;j--)
{
if(i==grid.length-1&&j!=grid[0].length-1)
dp[i][j]=grid[i][j]+dp[i][j+1];
else if (i!=grid.length-1&&j==grid[0].length-1)
{
dp[i][j]=grid[i][j]+dp[i+1][j];
}
else if (i!=grid.length-1&&j!=grid[0].length-1)
{
dp[i][j]=grid[i][j]+Math.min(dp[i+1][j], dp[i][j+1]);
}
else {
dp[i][j]=grid[i][j];
}
}
return dp[0][0];
}
}
LeetCode中等题(二)的更多相关文章
- C#LeetCode刷题-二叉搜索树
二叉搜索树篇 # 题名 刷题 通过率 难度 220 存在重复元素 III 19.3% 中等 315 计算右侧小于当前元素的个数 31.9% 困难 327 区间和的个数 29.5% 困难 3 ...
- LeetCode中等题(三)
题目一: 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明:1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NULL, m ...
- LeetCode中等题(一)
题目一: 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表 ...
- leetcode 中等题(2)
50. Pow(x, n) (中等) double myPow(double x, int n) { ; unsigned long long p; ) { p = -n; x = / x; } el ...
- leetcode 中等题(1)
2. Add Two Numbers(中等) /** * Definition for singly-linked list. * struct ListNode { * int val; * Lis ...
- LeetCode简单题(二)
题目一: 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的 ...
- leetcode中等题
# Title Solution Acceptance Difficulty Frequency 1 Two Sum 44.5% Easy 2 Add Two Number ...
- 这样leetcode简单题都更完了
这样leetcode简单题都更完了,作为水题王的我开始要更新leetcode中等题和难题了,有些挖了很久的坑也将在在这个阶段一一揭晓,接下来的算法性更强,我就要开始分专题更新题目,而不是再以我的A题顺 ...
- LeetCode刷题笔记和想法(C++)
主要用于记录在LeetCode刷题的过程中学习到的一些思想和自己的想法,希望通过leetcode提升自己的编程素养 :p 高效leetcode刷题小诀窍(这只是目前对我自己而言的小方法,之后会根据自己 ...
随机推荐
- ioutils
import yaml import json import csv import configparser class IoUtils(object): """ dep ...
- WPscan扫描工具安装使用
WPScan是Kali Linux默认自带的一款漏洞扫描工具,它采用Ruby编写,能够扫描WordPress网站中的多种安全漏洞,其中包括WordPress本身的漏洞.插件漏洞和主题漏洞.最新版本WP ...
- MySQL的多表查询学习笔记
一.案例准备 create table dept( id int primary key auto_increment, name ) ); insert into dept values(null, ...
- 老段带你学鸟哥Linux视频教程 包含基础班+提高班
老段带你学鸟哥Linux视频教程 包含基础班+提高班,附带pdf文档. 目录结构如下: 目录:/-老段带你学鸟哥Linux视频教程 [.9G] ┣━━老段带你学鸟哥-服务器篇 [1009.4M] ┃ ...
- Spring boot+Thymeleaf传参跳转
$.ajax(): $.ajax({ type: "get", url:"/public/inform", async: true, data: detailJ ...
- 四种常见的数据结构、LinkedList、Set集合、Collection、Map总结
四种常见的数据结构: 1.堆栈结构: 先进后出的特点.(就像弹夹一样,先进去的在后进去的低下.) 2.队列结构: 先进先出的特点.(就像安检一样,先进去的先出来 ...
- 给Linux安装中文的man手册
查找 yum list |grep man.*zh 安装 sudo yum install man-pages-zh-CN.noarch 配置 alias cman='man -M /usr//sha ...
- loadrunner测试sql语句性能
最初的想法是是想通过录制在SQL Server2008的操作来着的,无奈试了即便都录不到查询的sql语句,网上查资料全是关于SQL 2000的(这部分有经验的欢迎指教). 于是只能通过直接调用load ...
- Vue 实现全局使用sass, less变量
首先 运行这行命令 npm install sass-resources-loader --save-dev: 在项目的build/utils.js中,找到 function generateLo ...
- stackADT
stack.h #ifndef STACK_H_INCLUDED #define STACK_H_INCLUDED #include <stdbool.h> typedef struct ...