一:方法总结
1.要求线性的时间复杂度
双指针,hash表
2.链表问题
找到倒数第k个结点:两个指针,指针A一个移动k次,再两个指针同时移动直到A到尾结点;由于A-B保持k的距离,因此B在倒数第k个结点上
找中间结点:快慢指针,快指针移动2次,慢指针移动1次;慢指针移动n次,快指针移动2n次,因此满指针在中间处。
判断链表是否有环以及环的长度:hash表或快慢指针,快慢指针:快指针1次,慢指针2次,第一次相遇则有环,第二次相遇慢指针走过的距离=环的长度
二:题目
121.买卖股票的最佳时机
给定一个数组 prices
,它的第 i
个元素 prices[i]
表示一支给定股票第 i
天的价格。
思路:定义min保存已遍历的数据中的最小数据,min之后的数据- min 得到利润
public int maxProfit(int[] prices) {
int ans=0;
int min=prices[0];
for ( int i=1;i<prices.length;i++){
if (prices[i]<min){
min=prices[i];
}
else if (prices[i]>min ){
ans=Math.max(ans,prices[i]-min);
}
}
return ans;
}
124.二叉树中的最大路径和
int max =Integer.Min_value;//基本数据类型需要定义为全局变量才能在方法中修改
public int maxPathSum(TreeNode root) {
dfs(root);
return max;
}
//返回node结点的最大贡献值,最大贡献值为结点的值+该结点某一个叶子结点的值
public int dfs(TreeNode node) {
if (node==null)//将空节点的值置为0
return 0;
//贡献值<=0 都作为0处理
int leftGain= Math.max(dfs(node.left),0);
int rightGain= Math.max(dfs(node.right),0);
max= Math.max(max,leftGain+rightGain+node.val);//此时node.val仍是原本的值
node.val=node.val+Math.max(leftGain,rightGain);
return node.val;
}
128.最长连续序列
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
思路:现将所有数字加入hashset,再遍历数组,找出某连续子序列的最小数字,统计长度。
public int longestConsecutive(int[] nums) {
Set<Integer> num_set = new HashSet<Integer>();
for (int num : nums) {
num_set.add(num);
}
int ans = 0;
for (int num : num_set) {
if (!num_set.contains(num - 1)) {//找某连续子列中的最小值
int currentNum = num;
int temp = 1;
while (num_set.contains(currentNum + 1)) {//记录长度
currentNum++;
temp++;
}
ans = Math.max(ans, temp);
}
}
return ans;
}
136.只出现一次的数字
思路:位运算,两个相同的数组做异或 = 0;非零数字与0做异或 = 数字本身
public int singleNumber(int[] nums) {
int single = 0;
for (int num : nums) {
single ^= num;
}
return single;
}
141.环形链表
给定一个链表,判断链表中是否有环。
思路:1.hashSet
2.快慢指针
ListNode fast = head;
ListNode slow = head;
while (fast.next != null) {
fast = fast.next;
if (fast.next != null)
fast = fast.next;
if (fast == slow)//先判断,避免链表长度<=2的情况
return true;
slow = slow.next;
}
return false;
}