Leetcode11 盛最多水的容器
给定 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i
的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。说明:你不能倾斜容器,且 n 的值至少为 2。
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例:
输入: [1,8,6,2,5,4,8,3,7] 输出: 49
思路:一开始我用暴力法直接解题,然后一顿操作猛如虎。一看打败的人只有百分之三十。。。也对,怎么可能暴力法是最优解呢。。
这道题可以用双指针法完成,一个指针指向最初的端点,一个指向最后,然后把两个指针向中央移动,并不断更新最大值,这样在指针碰撞之前,我们能够得到一个最大值,该值为我们所求。有一点需要注意,我们把指针向中央移动时,移动的是比较短的那个。为什么呢?我们都知道,面积为长度与宽度之积。随着指针向中央移动,其长度必定递减,为求更大的面积,我们必须要求更大的宽度。而我们又知,所求的宽度取决于更短的那个(木桶原理),若要宽度增大,我们唯有移动更短的端点,唯有这样才有使宽度增大的希望,才有使面积增大的希望。
class Solution {
public int maxArea(int[] height) {
int i = 0,j = height.length - 1,max = 0,now = 0;
while(i != j){
now = (j - i) * Math.min(height[i],height[j]);
max = max > now ? max : now;
if(height[i] >= height[j]){
j--;
}else{
i++;
}
}
return max;
}
}
Leetcode12 整数转罗马数字
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字 2写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。示例 1:
输入: 3 输出: “III”
示例 2:输入: 4 输出: “IV”
示例 3:输入: 9 输出: “IX”
示例 4:输入: 58 输出: “LVIII” 解释: L = 50, V = 5, III = 3.
示例 5:输入: 1994 输出: “MCMXCIV” 解释: M = 1000, CM = 900, XC = 90, IV = 4.
class Solution {
public String intToRoman(int num) {
String[] array = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
int[] number = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
int i = 0;
String get = "";
while(i <= 12){
if(num >= number[i]){
num -= number[i];
get += array[i];
}else{
i++;
}
}
return get;
}
}
Leetcode13 罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字 2写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。示例 1:
输入: “III” 输出: 3
示例 2:输入: “IV” 输出: 4
示例 3:输入: “IX” 输出: 9
示例 4:输入: “LVIII” 输出: 58 解释: L = 50, V= 5, III = 3.
示例 5:输入: “MCMXCIV” 输出: 1994 解释: M = 1000, CM = 900, XC = 90, IV = 4.
class Solution {
public int romanToInt(String s) {
String[] array = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
int[] number = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
int i = 0,num = 0;
while(!s.equals("")){
if(s.startsWith(array[i])){
s = s.substring((array[i]).length());
num += number[i];
}else{
i++;
}
}
return num;
}
}
Leetcode14 最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,“flow”,“flight”] 输出: “fl”
示例 2:输入: [“dog”,“racecar”,“car”] 输出: “”
解释: 输入不存在公共前缀。
说明:所有输入只包含小写字母 a-z 。
解析:遍历每一个字符串,比较当前最大公共前缀的字符串与当前字符串是否相等,不相等则更新最大公共前缀的字符串即可。
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0){
return "";
}
String max = strs[0];//最长公共前缀
int num = strs[0].length();//最长公共前缀的长度
int length = 0;//当前遍历的字符串长度与最长公共前缀的长度最小值
int i,j;
for(i = 1;i < strs.length;i++){
length = strs[i].length() > num ? num : strs[i].length();
for(j = 0;j < length;j++){
if(max.charAt(j) != strs[i].charAt(j)){
max = max.substring(0,j);
if(max.equals("")){
return "";
}
num = j;
break;
}
}
if(num > j) {
max = max.substring(0,j);
num = j;
}
}
return max;
}
}
Leetcode15 三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0
?找出所有满足条件且不重复的三元组。注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
解析:使用双指针法,由于要取三数之和,可以先将数组排序,然后遍历数组取出第一个数字,然后建立两个指针,分别指向第一个数字之后的一个数字和最后一个数字,判断三数之和是否为0,是则添加至链表,否则继续移动双指针,注意判断边界条件和去重即可。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
if(nums == null){
return null;
}else if(nums.length < 3){
return list;
}
int j,k;
Arrays.sort(nums);//排序
for(int i = 0;i < nums.length - 2;i++){
if(nums[i] > 0){//首数字大于0,易知三数之和不可能等于0
break;
}
if(i > 0 && nums[i] == nums[i-1]){//去重
continue;
}
j = i + 1;
k = nums.length - 1;
while(j < k){
if(nums[i] + nums[j] + nums[k] == 0){
if(j > i + 1 && nums[j] == nums[j-1]){//去重
j++;
}else if(k < nums.length - 1 && nums[k] == nums[k+1]){//去重
k--;
}else{
list.add(Arrays.asList(nums[i],nums[j],nums[k]));
j++;
k--;
}
}else if(nums[i] + nums[j] + nums[k] > 0 && j < k - 1){
k--;
}else if(nums[i] + nums[j] + nums[k] < 0 && j < k - 1){
j++;
}else {
break;
}
}
}
return list;
}
}
Leetcode16 最接近的三数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
解析:这一题运用双指针法可以轻松解决,由于这一题与上题十分相似,故不重复解题思路了。
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);//排序
int j,k,num = nums[0] + nums[1] + nums[nums.length-1];//num为三数之和
for(int i = 0;i < nums.length - 2;i++){
if(i > 0 && nums[i] == nums[i-1]){//去重
continue;
}
j = i + 1;
k = nums.length - 1;
while(j < k){
int sum = nums[i] + nums[j] + nums[k];
if(Math.abs(target - sum) < Math.abs(target - num)) {
num = sum;
}
if(sum > target) {
k--;
}else if(sum < target) {
j++;
}else {
return target;
}
}
}
return num;
}
}
Leetcode17 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:“23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
解析:实话实说,这道题挺简单的,真的没啥好说的。。。
class Solution {
public List<String> letterCombinations(String digits) {
List<String> list = new ArrayList<String>();
if(digits == null){
return null;
}else if(digits.length() == 0){
return list;
}
char[] chArray = digits.toCharArray();
char[][] getArray = {{'a','b','c'},{'d','e','f'},{'g','h','i'},{'j','k','l'},{'m','n','o'},{'p','q','r','s'},{'t','u','v'},{'w','x','y','z'}};
int[] x = new int[chArray.length];
int all = 1;
for(int i = 0;i < chArray.length;i++){
if(chArray[i] == '7' || chArray[i] == '9'){
all *= 4;
x[i] = 4;
}else{
all *= 3;
x[i] = 3;
}
}
int least = all,j,k,num;
char[][] arr = new char[all][chArray.length];
for(int i = 0;i < chArray.length;i++){
least /= x[i];
num = least;
j = 0;
k = 0;
while(j < all){
for(;j < num;j++){
arr[j][i] = getArray[chArray[i] - '2'][k];
}
num += least;
k = k == x[i] - 1 ? 0 : k + 1;
}
}
for(int i = 0;i < all;i++){
list.add(new String(arr[i]));
}
return list;
}
}
Leetcode19 删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
解析:使用快慢指针
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode left = head,right = head,p = null;//p为left的前一个节点
int i = 0;
while(right.next != null){
right = right.next;
if(++i >= n){
p = left;
left = left.next;
}
}
//left为要删除的节点
if(p == null){
return head.next;
}else{
p.next = left.next;
}
return head;
}
}
Leetcode20 有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false
示例 4:
输入: “([)]”
输出: false
示例 5:
输入: “{[]}”
输出: true
解析:堆栈的基本应用
class Solution {
public boolean isValid(String s) {
if(s.length() == 0){
return true;
}
Stack<Character> stack = new Stack<Character>();
char[] charArray = s.toCharArray();
for(int i = 0;i < charArray.length;i++){
if(charArray[i] == '(' || charArray[i] == '{' || charArray[i] == '['){
stack.push(charArray[i]);
}else if(charArray[i] == ')'){
if(stack.empty() || stack.pop() != '('){
return false;
}
}else if(charArray[i] == '}'){
if(stack.empty() || stack.pop() != '{'){
return false;
}
}else if(charArray[i] == ']'){
if(stack.empty() || stack.pop() != '['){
return false;
}
}
}
if(stack.empty()){
return true;
}
return false;
}
}