1. 两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
class Solution {
public int[] twoSum(int[] nums, int target) {
int length = nums.length;
for(int i = 0; i < length; i++){
for(int j = i + 1; j < length; j++){
if(target == (nums[i] + nums[j])){
return new int[]{i,j};
}
}
}
return null;
}
}
执行用时 内存消耗
38 ms 40.6 MB
官方答案:
使用HashMap,将数据逐个加入,每次加入时计算该数对应的解然后判断是否map中是否存在,若存在则返回对应的key和该数的值
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
}
2.两数之和
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
我的答案:参照了官方答案
对所有ListNode使用一个变量替代,初始化一个表示取模结果的变量carry
当ab任一不为空时获取ab的val,并将取余后的结果加入结果的下一个节点,将取模的结果存入carry下次循环使用,然后让ab指向下一个节点,循环结束后若carry大于0则将值赋给下一个节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode a = l1;
ListNode b = l2;
ListNode c = new ListNode(0);
ListNode d = c;
int carry = 0;
while(a != null || b != null){
int l11 = (a != null)? a.val:0;
int l22 = (b != null)? b.val:0;
int sum = carry+l11+l22;
carry=sum/10;
d.next=new ListNode(sum%10);
d=d.next;
if(a!=null){
a = a.next;
}
if(b != null){
b = b.next;
}
}
if(carry>0){
d.next = new ListNode(carry);
}
return c.next;
}
}
3. 无重复字符的最长字串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
解法:转自力扣用户LeetCode的答案
暴力破解:遍历数组,对每一个字符进行查重,查重方式是取当前字符为基本字符,然后检测字符串中是否有重复字符,若没有则再取当前字符和后一位字符重复上述步骤
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
int ans = 0;
for (int i = 0; i < n; i++) // 遍历每个字符
for (int j = i + 1; j <= n; j++) // 将当前字符和后几位字符查重校验
if (allUnique(s, i, j)) ans = Math.max(ans, j - i);
return ans;
}
public boolean allUnique(String s, int start, int end) {
Set<Character> set = new HashSet<>();
for (int i = start; i < end; i++) {
Character ch = s.charAt(i);
if (set.contains(ch)) return false;
set.add(ch);
}
return true;
}
}
滑动窗口:
如图所示,我们称索引 i ~ j 之间的区间为窗口,当当前字符在集合set中不存在时将该字符加如集合set并将索引 j + 1 ,当当前字符在集合set中存在时删除集合set中的该字符(字符串第 i 位)并将i+1
最好情况是没有重复字符返回所有长度或都为重复字符返回1
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
Set<Character> set = new HashSet<>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {
// try to extend the range [i, j]
if (!set.contains(s.charAt(j))){
set.add(s.charAt(j++));
ans = Math.max(ans, j - i);
}
else {
set.remove(s.charAt(i++));
}
}
return ans;
}
}
优化滑动窗口:
优化在于只需要遍历一次即执行 n 次,遍历时判断当前字符是否在集合map中,若存在则将索引 i 赋值集合map中相同字符的 value(该字符索引值) ,然后给结果附上当前窗口大小( j - i + 1)和结果比较的最大值,之后再将当前字符和索引位置加入集合map
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>(); // current index of character
// try to extend the range [i, j]
for (int j = 0, i = 0; j < n; j++) {
if (map.containsKey(s.charAt(j))) {
i = Math.max(map.get(s.charAt(j)), i);
}
ans = Math.max(ans, j - i + 1);
map.put(s.charAt(j), j + 1);
}
return ans;
}
}
7. 整数转换
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
解题思路:
循环获取最后一位数并对原来的数取余
遇到的问题:
数值可能溢出,则再第七位判断数值的大小是否大于最大数/10的值
class Solution {
public int reverse(int x) {
int result = 0;
int temp = 1 << 31 ;
while(x != 0){
if(((result == Integer.MAX_VALUE && (x % 10) > 7) || result > Integer.MAX_VALUE / 10) ||
((result == Integer.MIN_VALUE / 10 &&( x % 10) < -8) || result < Integer.MIN_VALUE / 10)){
return 0;
}
temp = result;
result = result * 10 + x % 10;
x /= 10;
}
return result;
}
}
执行用时 :1 ms, 在所有 java 提交中击败了100.00%的用户
内存消耗 :33.8 MB, 在所有 java 提交中击败了79.07%的用户
9. 回文数
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入: 121
输出: true
示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
本答案搬运自力扣用户MisterBooo的答案:
解读:将整数转为字符串之后反转字符串,再将输入的整数转为字符串和转换的字符串比较
class Solution {
public boolean isPalindrome(int x) {
/**
* x + ""是将int转为String,reverse()将字符串反转,
* toString()将StringBuilder对象转化为String
*/
String reversedStr = (new StringBuilder(x + "")).reverse().toString();
return (x + "").equals(reversedStr);
}
}
本答案搬运自力扣用户LeetCode的答案:
解读:根据题意先判断肯定不为回文数的情况:即为负数和整数最后一位为0的情况(除0外)
然后获取输入数的后一半的数值,获取后将该数值和计算后的原数值比较,具体见下方注释
public class Solution {
public bool IsPalindrome(int x) {
// 当输入的数为负数或输入的数最后一位是0
if(x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
/**
* revertedNumber 是输入的数的后一半数值的逆转的数值,如12321最后得到123
* 当输入的数大于revertedNumber时revertedNumber再取输入数的最后一位为自身个位
* 同时输入的数去掉最后一位数
*/
int revertedNumber = 0;
while(x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
/**
* 还要考虑输入的数长度为奇数时的情况
* 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber=123
* 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
*/
return x == revertedNumber || x == revertedNumber/10;
}
}
13. 罗马数字转整数
罗马数字包含以下七种字符: 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.
答案来自力扣用户guanpengchn的答案
class Solution {
public int romanToInt(String s) {
Map<String, Integer> map = new HashMap<>();
map.put("I", 1);
map.put("IV", 4);
map.put("V", 5);
map.put("IX", 9);
map.put("X", 10);
map.put("XL", 40);
map.put("L", 50);
map.put("XC", 90);
map.put("C", 100);
map.put("CD", 400);
map.put("D", 500);
map.put("CM", 900);
map.put("M", 1000);
int ans = 0;
for(int i = 0;i < s.length();) {
if(i + 1 < s.length() && map.containsKey(s.substring(i, i+2))) {
ans += map.get(s.substring(i, i+2));
i += 2;
} else {
ans += map.get(s.substring(i, i+1));
i ++;
}
}
return ans;
}
}
执行用时 :14 ms, 在所有 Java 提交中击败了12.68%的用户
内存消耗 :37.3 MB, 在所有 Java 提交中击败了13.04%的用户
答案来自力扣用户donespeak的答案
class Solution {
public int romanToInt(String s) {
int sum = 0;
int preNum = getValue(s.charAt(0));
for(int i = 1;i < s.length(); i ++) {
int num = getValue(s.charAt(i));
if(preNum < num) {
sum -= preNum;
} else {
sum += preNum;
}
preNum = num;
}
sum += preNum;
return sum;
}
private int getValue(char ch) {
switch(ch) {
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return 0;
}
}
}
14. 求最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
答案来自力扣用户LeetCode的答案
解读(详解见链接):
比哪里每个字符串数组的成员,遍历时获取当前字符串和后一个字符串的公共部分,若相同部分位置不为0(不在开头)获取该部分字符串,再与下一个比较获取相同部分字符串,最后输出
public String longestCommonPrefix(String[] strs) {
if (strs.length == 0) return "";
String prefix = strs[0];
for (int i = 1; i < strs.length; i++)
while (strs[i].indexOf(prefix) != 0) {
prefix = prefix.substring(0, prefix.length() - 1);
if (prefix.isEmpty()) return "";
}
return prefix;
}
20. 有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false
示例 4:
输入: “([)]”
输出: false
示例 5:
输入: “{[]}”
输出: true
答案来自力扣用户LeetCode的答案
class Solution {
// Hash table that takes care of the mappings.
private HashMap<Character, Character> mappings;
// Initialize hash map with mappings. This simply makes the code easier to read.
public Solution() {
this.mappings = new HashMap<Character, Character>();
this.mappings.put(')', '(');
this.mappings.put('}', '{');
this.mappings.put(']', '[');
}
public boolean isValid(String s) {
// Initialize a stack to be used in the algorithm.
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// If the current character is a closing bracket.
if (this.mappings.containsKey(c)) {
// Get the top element of the stack. If the stack is empty, set a dummy value of '#'
char topElement = stack.empty() ? '#' : stack.pop();
// If the mapping for this bracket doesn't match the stack's top element, return false.
if (topElement != this.mappings.get(c)) {
return false;
}
} else {
// If it was an opening bracket, push to the stack.
stack.push(c);
}
}
// If the stack still contains elements, then it is an invalid expression.
return stack.isEmpty();
}
}