输入: s = “leetcode”, wordDict = [“leet”, “code”]
输出: true
解释: 返回 true,因为 “leetcode” 可以被拆分成 “leet code”。
输入: s = “applepenapple”, wordDict = [“apple”, “pen”]
输出: true 解释: 返回true, 因为 “applepenapple” 可以被拆分成 “apple pen apple”。
注意你可以重复使用字典中的单词。
输入: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
输出: false
dp[i]
表示长度为i的字符串,通过分割后是否在wordDict中。j
对长度为i的字符串进行分割,得到两个子串,如果dp[j]
为true,表示子串[0, j - 1]
在wordDict中;于是还需要判断剩下的子串[j, i - 1]
是否在wordDict中。dp[i] = true
,并且无需使用j继续分割字符串。public boolean wordBreak(String s, List<String> wordDict) {
boolean[] dp = new boolean[s.length() + 1];//dp[i]表示长度为i的字符串,分割后是否在wordDict中
dp[0] = true;
for (int i = 1; i <= s.length(); i++) {
for (int j = 0; j < i; j++) {// 通过j分割字符串,当dp[j]为true时,看subString(j,i)是否在wordDict中
String sub = s.substring(j, i);
if (dp[j] && wordDict.contains(sub)){// 不仅要j之前的子串在在wordDict中,还要求从j开始的子串也要在在wordDict中
dp[i] = true;
break;// 无需继续遍历下去
}
}
}
return dp[s.length()];
}
HashMap
存储已经访问过的节点,如果链表存在环,则某一节点的下一节点已经被访问过;不存在环,会一直遍历到null节点
(尾节点的下一节点)。public boolean hasCycle(ListNode head) {
HashMap<ListNode, Integer> map = new HashMap<>();
while (head != null) {
if (!map.containsKey(head)) {
map.put(head, 1);
head = head.next;
} else {
return true;// 已经访问过的节点,说明存在环,直接返回true
}
}
return false;
}
false
。0ms
:public boolean hasCycle(ListNode head) {
if (head == null) {
return false;
}
ListNode slow = head;// slow跑一步
ListNode fast = head.next;// fast跑两步
while (slow != fast) {
if (fast == null || fast.next == null) {// 无环:单数节点,fast指向null;双数节点,fast的next节点为null
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
push
、pop
、peek
实现对应的push、pop、top
功能。93ms
:public class MinStack {
List<Integer> value;
Stack<Integer> stack;
/**
* initialize your data structure here.
*/
public MinStack() {
value=new ArrayList<>();
stack = new Stack<>();
}
public void push(int x) {
stack.push(x);
value.add(x);
}
public void pop() {
Integer top=stack.pop();
value.remove(top);
}
public int top() {
return stack.peek();
}
public int getMin() {
int min=Integer.MAX_VALUE;
for (int i=0;i<value.size();i++){
if (min>value.get(i)){
min=value.get(i);
}
}
return min;
}
}
List.get(i)
存储stack中有i+1
个元素时的最小元素。代码修改之后的运行时间47ms
:public class MinStack {
List<Integer> value;
Stack<Integer> stack;
public MinStack() {
value = new ArrayList<>();
stack = new Stack<>();
}
public void push(int x) {
stack.push(x);
if (value.size() == 0) {
value.add(x);
} else {
value.add(Math.min(value.get(value.size() - 1), x));// value[i]记录stack中有i个元素时的最小值
}
}
public void pop() {
Integer top = stack.pop();
value.remove(value.size() - 1);
}
public int top() {
return stack.peek();
}
public int getMin() {
return value.get(value.size() - 1);
}
}
48ms
:public class MinStack {
Stack<Integer> stack1;
Stack<Integer> stack2;
public MinStack() {
stack1 = new Stack<>();
stack2 = new Stack<>();
}
public void push(int x) {
stack1.push(x);
if (stack2.isEmpty()) {
stack2.push(x);
} else {
stack2.push(Math.min(stack2.peek(), x));
}
}
public void pop() {
stack1.pop();
stack2.pop();
}
public int top() {
return stack1.peek();
}
public int getMin() {
return stack2.peek();
}
}
输出:Reference of the node with value = 8
输出:Reference of the node with value = 2
输出:null
HasMap
存储headA中的所有节点。再遍历headB,然后看HasMap
中是否已经存在。8ms
:public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
HashMap<ListNode, Integer> hashMap = new HashMap<>();
while (headA != null) {
hashMap.put(headA, 1);
headA = headA.next;
}
while (headB != null) {
if (hashMap.containsKey(headB)) {
return headB;
}
headB = headB.next;
}
return null;
}
headA
和headB
有交点,则相交后的公共部分长度相等。headA
和headB
的长度headA
或者headB
的指向,使得二者剩余长度与较短者一致。1ms
:public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int len1 = 0, len2 = 0;
ListNode p = headA;
ListNode q = headB;
while (p != null) {
len1++;
p = p.next;
}
while (q != null) {
len2++;
q = q.next;
}
if (len1 > len2) {// 更新p或q的指向,使得headA和headB中剩下节点数一致
while (len1 != len2) {
headA = headA.next;
len1--;
}
} else {
while (len1 != len2) {
headB = headB.next;
len2--;
}
}
while (headA != null) {
if (headA == headB) {
return headA;
}
headA = headA.next;
headB = headB.next;
}
return null;
}
headA
将经过X1、y、X2,最终到达公共节点;headB
将经过X2、y、X1,终到达公共节点。headA
将经过X1、X2,最终到达headB
的null节点;headB
将经过将经过X2、X1,最终到达headA
的null节点。1ms
:public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p = headA;
ListNode q = headB;
while (p != q) {// 要么都达到一圈以后的末尾,要么都达到交点
p = (p != null) ? p.next : headB;
q = (q != null) ? q.next : headA;
}
return p;
}
输入: [3,2,3]
输出: 3
输入: [2,2,1,1,1,2,2]
输出: 2
10ms
:public int majorityElement(int[] nums) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
for (Integer key : map.keySet()) {
if (map.get(key) >= (nums.length / 2 + 1)) {// 判断个数是否大于一半
return key;// 返回对应key即元素值
}
}
return -1;
}
1ms
:public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
输入: [2,7,9,3,1]
输出: 12
解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。
i-2
;不打劫第i家,上一家是i-1
。即dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
dp[i] = Math.max(dp[i - 1], nums[i]);
。要么打劫第0家,要么打劫第1家。0ms
:public int rob(int[] nums) {
if (nums.length==0){
return 0;
}
int[] dp = new int[nums.length];// dp[i]表示打劫至第i家时,所获得的最大钱财数
dp[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
if (i - 2 >= 0) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
} else {
dp[i] = Math.max(dp[i - 1], nums[i]);
}
}
return dp[nums.length-1];
}
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
0ms
:public ListNode reverseList(ListNode head) {
ListNode p = null;
while (head != null) {
ListNode temp = new ListNode(head.val);
temp.next = p;
p = temp;
head = head.next;
}
return p;
}
1->2->3->4->5->NULL
借用指针变成null <- 1 <- 2 <- 3 <- 4 <- 5
cur.next=pre
,然后更新pre和cur指针的指向。**注意:**在更改cur的指向前,一定要使用多余的指针保留其原始的next结点。0ms
:public ListNode reverseList(ListNode head) {
ListNode pre=null;
ListNode cur=head;
while (cur!=null){
ListNode temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;
}
return pre;
}