描述:
给定一个整数数组 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) {
for(int i = 0;i<nums.length;i++) {
for(int j = i+1;j<nums.length;j++) {
if(nums[i] + nums[j] == target) {
return new int[] { i, j };
}
}
}
throw new IllegalArgumentException("没有找到");
}
}
缺点就是时间复杂度为O(n^2)
因为最近有复习到java中的集合,了解到hashmap的特点,可以有效找到元素与索引的关系,可以使时间复杂度降至O(1)
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i<nums.length;i++) {
map.put(nums[i], i);
}
for(int i = 0;i<nums.length;i++) {
int c = target - nums[i];
if(map.containsKey(c) && map.get(c) != i) {
return new int[] {i,map.get(c)};
}
}
throw new IllegalArgumentException("没有找到");
}
}
描述:
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
思路:
按照我们小学学习的两个多位数的相加,从各位开始,各位与各位相加,如果大于10则进位,保留其与10的余数。接下来十位,百位,亦是如此。直到有一个数的没有更高位,则把另一个数的剩余高位补到结果的高位,此时需要判断,是否有进位,如有进位,还需把进位也加之到结果上。
这道题主要是对链表的一些操作。
具体步骤:
(1)判断两个链表的所取结点至少有一个不为null(表示相加还未结束)
(2)如果有一个链表索取结点已经为null了,则让其所取数为0,便于另一个数相加。
(3)相加两个所取的数字之和sum
(4)计算sum对10的商值,即目前的进位。
(5)在结果链表上保存当前sum对10的余数,即结果数字的当前位。
(6)将两个链表的指针都指向下一个结点。继续从第(1)步循环进行,直到不满足(1)的条件。
(7)判断是否两数相加结束后仍存在进位,如果有,则在结果链表上创建一个新的结点,用来保存最后一次的进位(结果边界判断)。
/**
* 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 t = new ListNode(0);
ListNode s = t;
int c = 0;
while (l1 != null || l2 != null) {
int x = l1 == null ? 0 : l1.val;
int y = l2 == null ? 0 : l2.val;
int sum = x + y + c;
c = sum /10;
sum = sum %10;
s.next = new ListNode(sum);
s = s.next;
if(l1 != null) {
l1 = l1.next;
}
if(l2 != null) {
l2 = l2.next;
}
}
if(c != 0) {
s.next = new ListNode(c);
}
return t.next;
}
}
描述:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
思路: 逐步检查所有的子字符串,找到最大不重复子字符串 ,暴力循环
class Solution {
public int lengthOfLongestSubstring(String s) {
//两次循环应该可以搞定
//1.为空直接退出
if (s == null) {
return 0;
}
//2.不为空时
int len = s.length();
List<Character> list = new ArrayList<>();
int count = 0;
for (int i = 0; i < len; i++) {
for (int j = i; j < len; j++) {
if (list.contains(s.charAt(j))) {
break;
} else {
list.add(s.charAt(j));
}
}
count = Math.max(count, list.size());
//当count大于等于剩下字符串的长度时,不再遍历
if (count >= len - 1 - i) {
break;
}
list.clear();
}
return count;
}
}
描述:
给定两个大小为 m 和 n 的有序数组 `nums1` 和 `nums2`。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 `nums1` 和 `nums2` 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
思路:
把长度为m和长度为n的两个数组的数据放在一个新的数组中,然后对数组进行排序,找到中位数。
找中位数的时候,因为组合后的数组元素个数(m + n)的奇偶性不确定,如果是奇数的话,那么中位数就是第(m+n)/ 2 个元素,如果是偶数的话,那么中位数就是第(m + n )/ 2 个元素和第(m + n)/ 2 + 1个。
我们可以利用int整型向下取整的特点,把上面两种情况归结为一种通用的解法,我们可以找到下标(m + n - 1)/ 2和下标(m + n )/ 2元素,然后求两数的平均值。
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int [] result = Arrays.copyOf(nums1, nums1.length + nums2.length);
/**将一个数组片段复制到另一个数组的指定位置
* System.arraycopy(src, srcPos, dest, destPos, length)
* src: 源数组
* srcPos: 从源数组复制数据的起始位置
* dest: 目标数组
* destPos: 复制到目标数组的起始位置
* length: 复制的长度
*/
System.arraycopy(nums2, 0, result, nums1.length, nums2.length);
Arrays.sort(result);
double d = (double)(result[(nums1.length +
nums2.length -1)/2] +
result[(nums1.length + nums2.length )/2])/2;
return d;
}
}