很久没做这种AC,WA式的编程题了。。主要还是为了练习还有弥补一下没好好学的数据结构,很是艰难的做了leetcode上的三道题,一方面很久没做,一方面根本对java中容器的相关标准不熟悉。先题解。
题目1.Two Sum
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,Because nums[
0] + nums[
1] = 2 + 7 = 9,return [
0,
1].
大意:英文很差,具体啥意思我是看不懂的,不过几个专有名词还是认识的,大概也就是讲在一个数组里面找到两个数,使他们的和等于目标值,返回这两个数组的下标。
分析:第一反应肯定是依次搜索。复杂度O(n^2),遍历每一种可能的组合,想想肯定超时也就没试。然后想着有没有办法把第二层查找复杂度给降低,这时候呼之欲出就是用map了。复杂度就变成O(n)了。
下面是代码:
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] ans=new int[2];
HashMap<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){
if(map.containsKey(target-nums[i])&&i!=map.get(target-nums[i]))
return new int[]{i,map.get(target-nums[i])};
}
return ans;
}
}
思路:利用map根据key查找value的特性,遍历一遍数组,第二层时找到value为target-nums[i]即可。更低的复杂度的暂时没想出来。
题目2:Add Two Numbers
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 Explanation: 342 + 465 = 807.
大意:题目没看。。直接看example大概就是两个用链表表示的数相加,然后返回一个链表形式的两数的和。
分析:链表已经在注释中声明了,其实就是模拟一下数学上的两数相加,其实就是满10进位,从最低位开始满10向前进位即可。
代码:
/**
* 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 node=new ListNode(0);
if(l1==null&&l2==null)return l1;
sol(node,l1,l2);
return node;
}
public void sol(ListNode res,ListNode l1,ListNode l2){
if(l1!=null)res.val+=l1.val;
else l1=new ListNode(0);
if(l2!=null)res.val+=l2.val;
else l2=new ListNode(0);
ListNode node=new ListNode(0);
if(res.val>=10){ //进位处理
res.val=res.val-10;
node.val=1;
res.next=node;
}
if(l1.next!=null||l2.next!=null){
res.next=node;
sol(res.next,l1.next,l2.next);
}
}
}
没什么好解释的就是个简单的进位处理和链表的理解。
题目三
Longest Substring Without Repeating Characters
Given a string, find the length of the
longest substring
without repeating characters.
Examples:
Given "abcabcbb"
, the answer is "abc"
, which the length is 3.
Given "bbbbb"
, the answer is "b"
, with the length of 1.
Given "pwwkew"
, the answer is "wke"
, with the length of 3. Note that the answer must be a substring, "pwke"
is a subsequence and not a substring.
大意:substring我肯定是看不懂什么意思的,看了下例子,大概应该就是在一个给定的字符串中寻找一个最长的连续不重复的字符子串。
分析:初期看到这个很熟悉,很自然的想到了DP。。然后发现dp已经忘光了,怎么搞不出递推式,暴力写找出所有可能验证一遍一看就太过弱智,稳定超时就没写了。后来去看了Solution里大佬们的解法恍然大悟,大佬不愧是大佬。
代码:
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) {
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;
}
}
大概就是建立一个字符集合,由于集合的特性--相异性,emmm....很显然很适合这道题,用i和j分别标记最长串的头和尾的下标,如果每次集合没包括下一个集合,那么就继续寻找即可,同时结果为当前结果和j-i两者之间的最大值,另外,如果包括了这个字符,那么把头部重复的字符给去除出集合即可,找到最后留下的一定是最大的字符串长度。
收获:
还是有所收获的,收获主要还是Java中容器的一些规范,比如容器属性不能用基础属性名,如int ,char之类的,应该用封装类名Integer和Character,还有Hashmap的两种声明在不同应用环境中的不同。还有一些容器中的书写习惯和C++中STL的容器有所区别的,希望自己对Java越来越熟悉。