LeetCode困难题(一)
题目一:
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
方法一:
1、这是一个给定一个反转数链表反转,先实现整个链表反转;
2、设置pre=null,curr=head, while(curr!=null) 定义一个新的节点保证当前节点的下一个节点 ListNode temp=curr.next;
3、curr.next=pre将当前节点指针往前指,然后将当前节点赋值给pre,curr=temp,最后返回pre,就是反转后的链表;
4、下面实现多个链表的反转,先设置一个哑结点,ListNode dummy=new ListNode(0);
5、ListNode dummy.next=head,ListNode pre=dummy,end=dummy;
6、开始通过判断end进行循环,while(end!=null) for(int i=0;i<k&&end!=null) end=end.next;
7、如果end==null表示剩下的节点小于阈值k,直接跳出循环break;
8、定义一个next节点存放end的最后指向的位置 ListNode=end.next,在定义一个开始节点ListNode start=pre.next;
9、end.next断开链表,end.next=null;
10、pre.next=reverse(start)实现链表的反转,将start放置到最后;
11、将start指向之前end存放的节点,start.next=next;
12、pre节点和end节点都赋值给start;
13、返回哑结点dummy.next;
具体代码:
class Solution {
public ListNode reverseKGroup(ListNode head, int k) { ListNode dummy=new ListNode(0);
dummy.next=head;
ListNode pre=dummy;
ListNode end=dummy; while(end!=null)
{
for(int i=0;i<k&&end!=null;i++) end=end.next;
if(end==null) break; ListNode next=end.next;
ListNode start=pre.next;
end.next=null;
pre.next=reverse(start);
start.next=next;
pre=start;
end=start;
}
return dummy.next;
} public ListNode reverse(ListNode head)
{
ListNode pre=null;
ListNode curr=head;
while(curr!=null)
{
ListNode temp=curr.next;
curr.next=pre;
pre=curr;
curr=temp;
} return pre;
}
}
题目二:
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
方法一:
1、对每一列进行遍历,求出每一列的接水量;
2、整体的思路是,对于每一列求出其左边最大值和右边最大值,再求其最小值,将这个最小值和这个列进行比较;
3、如果最小值>列长度,则min-nums[i],否则接水量为0;
具体代码:
class Solution {
public int trap(int[] height) { int sum=;
for(int i=;i<height.length-;i++)
{
int left_max=;
for(int j=i-;j>=;j--)
{
if(height[j]>left_max)
left_max=height[j];
} int right_max=;
for(int j=i+;j<height.length-;j++)
{
if(height[j]>right_max)
right_max=height[j];
} int min=Math.min(left_max, right_max);
if(height[i]<min)
sum=sum+(min-height[i]);
}
return sum;
}
}
方法二:
1、对于上述的方法使用了二重循环时间复杂度较高,每次都需要确定某一值的左边最大值和右边最大值;
2、我们想要减少上面的重复计算,用动态规划将数值进行存储;
3、动态方程:max_left[i]=Math.max(max_left[i-1],height[i-1]);
4、对于右采用同样的方式,需要求其最小值,直接进行调用,int min=Math.min(max_left[i],max_right[i]);
5、思路和方法一基本相同,只是用空间换取时间;
具体代码:
class Solution {
public int trap(int[] height) { int sum=0;
int max_left[]=new int[height.length];
int max_right[]=new int[height.length]; for(int i=1;i<height.length-1;i++)
max_left[i]=Math.max(max_left[i-1], height[i-1]); for(int i=height.length-2;i>=0;i--)
max_right[i]=Math.max(max_right[i+1], height[i+1]); for(int i=1;i<height.length-1;i++)
{
int min=Math.min(max_left[i], max_right[i]);
if(height[i]<min)
sum=sum+(min-height[i]);
}
return sum;
}
}
方法三:
1、双指针
具体代码:
public int trap(int[] height) {
int sum = 0;
int max_left = 0;
int max_right = 0;
int left = 1;
int right = height.length - 2; // 加右指针进去
for (int i = 1; i < height.length - 1; i++) {
//从左到右更
if (height[left - 1] < height[right + 1]) {
max_left = Math.max(max_left, height[left - 1]);
int min = max_left;
if (min > height[left]) {
sum = sum + (min - height[left]);
}
left++;
//从右到左更
} else {
max_right = Math.max(max_right, height[right + 1]);
int min = max_right;
if (min > height[right]) {
sum = sum + (min - height[right]);
}
right--;
}
}
return sum;
}
题目三:
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
示例 1:
输入: [1,2,0]
输出: 3
示例 2:
输入: [3,4,-1,1]
输出: 2
方法:
1、这道题的思路不是很容易能够想到,首先将数组中所有的小于等于0和大于n的数赋值为1;
2、然后将其进行转换变为负数,这个算法最精彩的部分是将转换后的数组的元素作为另一个元素的下标,并且将其赋值为绝对值的负值;
3、这样实现了数组中每一个前n个元素,出现过就将其设定为负值;
4、最后遍历循环,直到出现大于0的数就是我们要求的值,将其下标返回;
5、当然如果开始数组没有1,那么返回1为结果;
具体代码:
class Solution {
public int firstMissingPositive(int[] nums) { int n=nums.length;
int contain=0; for(int i=0;i<nums.length;i++)
{
if(nums[i]==1)
{
contain++;
break;
}
} if(contain==0)
return 1;
if(n==1)
return 2; for(int i=0;i<n;i++)
{
if(nums[i]<=0||nums[i]>n)
{
nums[i]=1;
}
} for(int i=0;i<n;i++)
{
int a=Math.abs(nums[i]);
if(a==n)
nums[0]=-Math.abs(nums[0]);
else
{
nums[a]=-Math.abs(nums[a]);
}
} for(int i=1;i<n;i++)
{
if(nums[i]>0)
return i;
} if(nums[0]>0)
return n; return n+1;
}
}
题目四:
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
方法一:
1、使用递归,可能不是很容易想到,模式字符串中有' .'和‘ *’,不知道应该如何下手;
2、其实着手点就在于*号,*号出现位置至少应该在第二位,就需要先判断第一个字符是否相同;
3、boolean first_match=s.charAt(0)==p.charAt(0)||p.charAt(0)==' .';
4、如果模式串的长度大于2并且第二位是*,就可以进行递归实现,return isMatch(s,p.substring(2))||first_match&&isMacth(s.substring(1),p);
5、否则,都向后移动一位;
具体代码:
class Solution {
public boolean isMatch(String s, String p) { if(p.isEmpty()) return s.isEmpty(); boolean first_match=(!s.isEmpty())&&(s.charAt(0)==p.charAt(0)||p.charAt(0)=='.'); if(p.length()>=2&&p.charAt(1)=='*')
{
return (isMatch(s, p.substring(2)))||(first_match&&isMatch(s.substring(1), p));
}
else
{
return first_match&&isMatch(s.substring(1), p.substring(1));
}
}
}
LeetCode困难题(一)的更多相关文章
- leetcode刷题指南
转载自:http://blog.csdn.net/lnho2015/article/details/50962989 以下是我个人做题过程中的一些体会: 1. LeetCode的题库越来越大,截止到目 ...
- 乘风破浪:LeetCode真题_025_Reverse Nodes in k-Group
乘风破浪:LeetCode真题_025_Reverse Nodes in k-Group 一.前言 将一个链表按照一定的长度切成几部分,然后每部分进行翻转以后再拼接成一个链表是比较困难的,但是这也能锻 ...
- 乘风破浪:LeetCode真题_010_Regular Expression Matching
乘风破浪:LeetCode真题_010_Regular Expression Matching 一.前言 关于正则表达式我们使用得非常多,但是如果让我们自己写一个,却是有非常大的困难的,我们可能想到状 ...
- 乘风破浪:LeetCode真题_006_ZigZag Conversion
乘风破浪:LeetCode真题_006_ZigZag Conversion 一.前言 到这里我们对基本的问题有了一定的理解,其中字符串的操作一直是一个比较困难的问题,这一点我们需要认真对待,采用合理的 ...
- 乘风破浪:LeetCode真题_004_Median of Two Sorted Arrays
乘风破浪:LeetCode真题_004_Median of Two Sorted Arrays 一.前言 说到算法,最难的就是一些需要通过分析得到一些递推公式或者有用的结论,进而用来解决问题的方法了. ...
- LeetCode刷题总结-数组篇(上)
数组是算法中最常用的一种数据结构,也是面试中最常考的考点.在LeetCode题库中,标记为数组类型的习题到目前为止,已累计到了202题.然而,这202道习题并不是每道题只标记为数组一个考点,大部分习题 ...
- LeetCode刷题总结-数组篇(中)
本文接着上一篇文章<LeetCode刷题总结-数组篇(上)>,继续讲第二个常考问题:矩阵问题. 矩阵也可以称为二维数组.在LeetCode相关习题中,作者总结发现主要考点有:矩阵元素的遍历 ...
- LeetCode刷题总结-数组篇(下)
本期讲O(n)类型问题,共14题.3道简单题,9道中等题,2道困难题.数组篇共归纳总结了50题,本篇是数组篇的最后一篇.其他三个篇章可参考: LeetCode刷题总结-数组篇(上),子数组问题(共17 ...
- LeetCode刷题总结-双指针、位运算和分治法篇
本文总结LeetCode上有关双指针.位运算和分治法的算法题,推荐刷题总数14道.具体考点分析如下图: 一.双指针 1.字符串和数组问题 题号:424. 替换后的最长重复字符,难度中等 题号:828. ...
随机推荐
- Apache和Nginx配置默认访问index.php
Apache: .htaccess文件配置 Options +FollowSymLinks RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d R ...
- numpy-sum函数
看一个例子就懂了 c = array([[[0, 1, 2, 0, 1, 2]], [[0, 1, 2, 0, 1, 2]]]) print('{0}\n'.format(c.shape)) prin ...
- iframe多层嵌套时,Jquery获取元素
在项目中,尤其是后台管理项目,会使用到iframe嵌套的网页,说起iframe,真的是个让人头疼的东西,能避开是最好避开.不然要请随身备好氧气瓶哈(因为管理和调试过程中往往会被气缺氧!!!哈哈哈~~~ ...
- js 根据data-i 降序排列
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 谈谈一些有趣的CSS题目-- 单行居中,两行居左,超过两行省略
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- PTA点赞狂魔
点赞狂魔 (25 分) 微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持.每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性.然而有这么一种人,他们会通过给自己看 ...
- c++写入注册表
一.说明: 注册表是Windows重要组成部分,注册表记录了大量有关电脑软硬件的信息.注册表中的值通过其名称标识.值名称由与键名相同的字符组成.值本身可以是字符串.二进制数据或者是32位无符 ...
- oracle 密码过期问题
密码过期问题: ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;
- 【C语言】创建一个函数,利用该函数将字符串中的小写字母转换为大写字母
原理: 这类题目主要通过ASCII(美国信息交换标准代码)码差值实现,A对应ASCII码十进制数字是65,a对应ASCII码十进制数字是97,即大小写字母之间ASCII码差值为32,想要将大写字母转换 ...
- python、js实现WGS84、高德(火星)、百度坐标转换
在日常工作学习中常会涉及到WGS84.高德(火星/谷歌).百度三种空间坐标系的坐标转换,本文将通过python.js两种语言实现坐标系的转换. 坐标系说明: wgs84:为一种大地坐标系,也是目前广泛 ...