1、两数之和【易】
一:暴力
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
//执行用时: 49 ms
//内存消耗: 38.2 MB
class Solution {
public int[] twoSum(int[] nums, int target) {
int [] arr=new int[2];
for(int i=1;i<nums.length;i++){
for(int j=0;j<i;j++){
if(nums[j]+nums[i]==target){
arr[0]=j;
arr[1]=i;
}
}
}
return arr;
}
}
暴力2(时间、空间复杂度同上)
//执行用时: 55 ms
//内存消耗: 41.7 MB
class Solution {
public int[] twoSum(int[] nums, int target) {
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[j]+nums[i]==target){
return new int[] {i,j};
}
}
}
return new int[-1];
}
}
二:哈希表
哈希表1:
- 时间复杂度:O(N)
- 空间复杂度:??
//执行用时: 4 ms
//内存消耗: 42.1 MB
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
if(nums == null || nums.length == 0){
return res;
}
HashMap<Integer, Integer> map = new HashMap<>();
//Map<Integer, Integer> map = new HashMap<>();也行
for(int i = 0; i < nums.length; i++){
int temp = target - nums[i];
if(map.containsKey(temp)){
res[1] = i;
res[0] = map.get(temp);
}
map.put(nums[i], i);
}
return res;
}
}
哈希表2:
优化:
//执行用时: 1 ms
//内存消耗: 41.3 MB
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
int[] arr = new int[2];
for(int i = 0; i < nums.length; i++) {
int tmp = target - nums[i];
if(map.containsKey(tmp)) {
arr[0] = map.get(tmp);
arr[1] = i;
return arr; //优化主要体现在这一步,如果符合条件,就提前结束循环
}
map.put(nums[i], i);
}
return nums;
}
}
哈希表3:
- 时间复杂度:O(N)
- 空间复杂度:O(N)
//执行用时: 2 ms
//内存消耗: 41.4 MB
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++) {
int tmp = target - nums[i];
if(map.containsKey(tmp)) {
int j = map.get(tmp);
return new int[]{i, j};
}
map.put(nums[i], i);
}
return new int[]{-1, -1};
}
}
2、两数相加【中】
//执行用时: 1 ms
//内存消耗: 41.6 MB
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
int n = 0;
while(l1 != null || l2 != null || n != 0) {
if(l1 != null) {
n += l1.val;
l1 = l1.next;
}
if(l2 != null) {
n += l2.val;
l2 = l2.next;
}
cur.next = new ListNode(n % 10);
cur = cur.next;
n /= 10;
}
return dummy.next;
}
}
3、无重复字符串的最长子串【中】
一:哈希表、滑动窗口
//执行用时: 4 ms
//内存消耗: 41.7 MB
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<>();
int len = 0;
for(int left = 0, right = 0; right < s.length(); right++) {
char c = s.charAt(right);
if(map.containsKey(c)) {
left = Math.max(map.get(c), left);//left取最右边的位置
}
len = Math.max(len, right - left +1);
map.put(s.charAt(right), right + 1);
}
return len;
}
}
二:滑动窗口
- 滑动窗口,保证每个窗口里字母都是唯一的
- 使用 int[] m来记录一个字母如果后面出现重复时,i 应该调整到的新位置21。 所以每次更新的时候都会保存 j + 1 ,即字母后面的位置
- j 表示子串的最后一个字母,计算子串长度为 j - i + 1
//执行用时: 1 ms
//内存消耗: 41.4 MB
class Solution {
public int lengthOfLongestSubstring(String s) {
int[] m = new int[128];
int len = 0;
for(int i = 0, j = 0; j < s.length(); j++){
i = Math.max(m[s.charAt(j)], i);
len = Math.max(len, j - i + 1);
m[s.charAt(j)] = j + 1;
}
return len;
}
}
4、寻找两个正序数组的中位数【难】
//执行用时: 3 ms
//内存消耗: 42.5 MB
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int len1 = nums1.length, len2 = nums2.length;
int len = len1 + len2;
int[] ans = new int[len];
for(int i = 0; i < len1; i++) {
ans[i] = nums1[i];
}
for(int i = len1; i < len; i++) {
ans[i] = nums2[i - len1];
}
Arrays.sort(ans);
int left = 0, right = len - 1;
/*
while(left < right) {
left++;
right--;
}
*/
if(len % 2 != 0) return (1.0 * ans[len / 2]);
return (1.0 * (ans[len / 2 - 1] + ans[len / 2]) / 2);
}
}
5、最长回文子串【中】
5. 最长回文子串
方法一:
//执行用时: 104 ms
//内存消耗: 44.9 MB
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
if(len < 2) return s;
boolean[][] dp = new boolean[len][len];//dp[i][j]:表示s[i][j]是否是回文串
int Imax = 1;
int Imin = 0;
char[] ss = s.toCharArray();
for(int i = 0; i < len; i++) {
dp[i][i] = true;// 初始化:单独一个字符肯定是回文子串
}
// 经验:dp区域是正方形的话,通常左下角区域无效不需要再填,因为走过的区域不用再走
for(int j = 1; j < len; j++) { // 上三角区域,按列从上到下填
for(int i = 0; i < j; i++) {
if(ss[i] != ss[j]) { // 首尾不相等时,必不是回文串
dp[i][j] = false;
} else {
//首尾相等时,有2种情况
// 情况1:s[i...j]长度不超过3,不用检查必为回文串
// 情况2:s[i...j]长度大于3,由s[i+1...j-1]来判断
dp[i][j] = j - i + 1 <= 3 || dp[i + 1][j - 1];
}
if(dp[i][j] && j - i + 1 > Imax) {
Imax = j - i + 1;
Imin = i;
}
}
}
return s.substring(Imin, Imin + Imax);
}
}