每日刷题记录,希望坚持。
题目:https://leetcode-cn.com/problems/delete-node-in-a-linked-list/ 【A-B-C-D】 思考:如果要删除节点B,一般是让节点A的next指向C。 因为此题参数只给了要删除的节点B,我们无法访问A,因此我们要把B换成C【即:A-C-C-D】,然后是C(原B)的next指向D【即:A-C-D】
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public void deleteNode(ListNode node) { node.val = node.next.val; node.next = node.next.next; } }题目:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/solution/er-cha-shu-de-zui-da-shen-du-by-leetcode/
思考:一般关于二叉树的遍历分为递归与非递归,求二叉树的最大深度要遍历二叉树,最后比较得出结果。
递归:DFS
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public int maxDepth(TreeNode root) { if(root == null){ return 0; } else{ int left = maxDepth(root.left);//求左子树最大深度 int right = maxDepth(root.right);//求右子树最大深度 return java.lang.Math.max(left,right)+1;//比较并加上此时所在节点 } } }非递归(1:利用栈将递归改为迭代,使用 DFS 策略访问每个结点,同时在每次访问时更新最大深度. (2:利用队列,使用BFS层序遍历每个节点
class Solution { public int maxDepth(TreeNode root) { if(root == null){ return 0; } Stack<TreeNode> stack = new Stack<>(); Stack<Integer> value = new Stack<>(); stack.push(root); value.push(1); int depth = 0; while(!stack.isEmpty()){ TreeNode node = stack.pop(); int tmp = value.pop(); depth = Math.max(depth,tmp); if(node.left != null){ stack.push(node.left); value.push(tmp+1); } if(node.right != null){ stack.push(node.right); value.push(tmp+1); } } return depth; } } class Solution { public int maxDepth(TreeNode root) { if(root == null){ return 0; } int depth = 0; Queue<TreeNode> q = new LinkedList<TreeNode>(); q.offer(root); while(!q.isEmpty()){ depth++; int size = q.size(); for(int i=0;i<size;i++){ TreeNode tmp = q.poll(); if(tmp.left != null){ q.offer(tmp.left); } if(tmp.right != null){ q.offer(tmp.right); } } } return depth; } }题目:https://leetcode-cn.com/problems/reverse-string/comments/ 思考:除了毫无难度的双指针移动,学到了异或交换的用法。
//普通版本 public void reverseString(char[] s) { int len = s.length; for(int i = 0; i < len / 2; i++) { char temp = s[i]; s[i] = s[len - 1 -i]; s[len - 1 -i] = temp; } } 异或: public void reverseString(char[] s) { int n = s.length; for (int i = 0; i < n / 2; ++i) { int j = n - 1 - i; s[i] ^= s[j]; s[j] ^= s[i];//s[j]=原来的s[i] s[i] ^= s[j];//s[i]=原来的s[j] } }题目:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/ 思考:
二叉搜索树:它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。【也方便查找】
利用这个性质中序遍历二叉搜索树刚好是一个升序数组。
class Solution { public TreeNode sortedArrayToBST(int[] nums) { return sortedBST(nums,0,nums.length-1); } public TreeNode sortedBST(int[] nums,int s,int e){ if(s > e){ return null; } int mid = (int)(s+e)/2; TreeNode node = new TreeNode(nums[mid]); node.left = sortedBST(nums,s,mid-1); node.right = sortedBST(nums,mid+1,e); return node; } }题目:https://leetcode-cn.com/problems/excel-sheet-column-number/ 思考:仔细观察会发现26一个轮回,可以列出表达式。
public int titleToNumber(String s) { char[] string = s.toCharArray(); int res = 0; for(int i=0;i<string.length;i++){ res = res * 26 + (string[i] - 'A' + 1); } return res; }题目:https://leetcode-cn.com/problems/reverse-linked-list/ 思考:既可以递归,也可以迭代
递归: class Solution { public ListNode reverseList(ListNode head) { return reverse(null,head); } public ListNode reverse(ListNode pre,ListNode now){ if(now == null) return pre; ListNode next = now.next; now.next = pre; return reverse(now,next); } } 迭代: class Solution { public ListNode reverseList(ListNode head) { ListNode pre = null; ListNode cur = head; while(cur!=null){ ListNode next = cur.next; cur.next = pre; pre = cur; cur = next; } return pre; } }题目:https://leetcode-cn.com/problems/pascals-triangle/ 思考:…怎么说,利用上一行的结果得出这一行的答案,然后记得特判一下。
class Solution { public List<List<Integer>> generate(int numRows) { List<List<Integer>> list = new ArrayList<>(); int[][] arr = new int[numRows][numRows]; for(int i=0;i<numRows;i++){ List<Integer> subList = new ArrayList<>(); for(int j=0;j<=i;j++){ if(j==0||j==i){ arr[i][j] = 1; } else{ arr[i][j] = arr[i-1][j-1]+arr[i-1][j]; } subList.add(arr[i][j]); } list.add(subList); } return list; } }题目:https://leetcode-cn.com/problems/single-number/ 思考:
1.交换律 a ^ b ^ c <=> a ^ c ^ b 2.任何数与0异或值为那个数本身 0 ^ n => n 3.相同的数异或值为0: n ^ n => 0
class Solution { public int singleNumber(int[] nums) { int res = 0; for(int i=0;i<nums.length;i++){ res = res ^ nums[i]; } return res; } }题目:https://leetcode-cn.com/problems/fizz-buzz/ 思考:好像没什么可说的,将数字转换为字符串的方式:String.valueOf(a); Integer.toString(a);
class Solution { public List<String> fizzBuzz(int n) { List<String> list = new ArrayList<>(); for(int i=1;i<=n;i++){ if(i%3==0&&i%5==0) { list.add("FizzBuzz"); } else if(i%3==0){ list.add("Fizz"); } else if(i%5==0){ list.add("Buzz"); } else{ list.add(String.valueOf(i)); } } return list; } }题目:https://leetcode-cn.com/problems/number-of-1-bits/ 思考:
使用 位掩码 来检查数字的第 i^{th}位。一开始,掩码m=1 因为 1 的二进制表示是 0000 0000 0000 0000 0000 0000 0000 0001 显然,任何数字跟掩码 1进行逻辑与运算,都可以让我们获得这个数字的最低位。检查下一位时,我们将掩码左移一位。 0000 0000 0000 0000 0000 0000 0000 0010 并重复此过程。
public class Solution { // you need to treat n as an unsigned value public int hammingWeight(int n) { int res = 0; int mask = 1; for(int i=0;i<32;i++){ if((n&mask) != 0){ res++; } mask<<=1; } return res; } }题目:https://leetcode-cn.com/problems/majority-element/ 思考:求数组中出现次数大于 ⌊ n/2 ⌋ 的元素。除了 ①用憨憨的二重循环求找出那个数 ②利用排序Arrays.sort(nums);,然后求nums[nums.length / 2]外 ③还可以利用投票法:
从第一个数开始count=1,遇到相同的就加1,遇到不同的就减1,减到0就重新换个数开始计数,总能找到最多的那个
class Solution { public int majorityElement(int[] nums) { int count = 0; int ans = 0; for(int i=0;i<nums.length;i++){ if(count == 0){ ans = nums[i]; count++; } else{ if(nums[i] == ans){ count++; } else{ count--; } } } return ans; } }题目:https://leetcode-cn.com/problems/merge-two-sorted-lists/ 思考:比较大小,然后移动链表。注意细节比较重要。
class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode ll = new ListNode(0); ListNode cur = ll; while(l1 != null && l2 != null){ if(l1.val < l2.val){ cur.next = l1; cur = cur.next; l1 = l1.next; } else{ cur.next = l2; cur = cur.next; l2 = l2.next; } } if(l1 == null){ cur.next = l2; } else{ cur.next = l1; } return ll.next; } } //差不多,但是思路有细微区别 class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if(l1 == null)return l2; if(l2 == null)return l1; ListNode cur = null; if(l1.val < l2.val){ cur = l1; l1 = l1.next; } else{ cur = l2; l2 = l2.next; } ListNode ans = cur; while(l1 != null && l2 != null){ if(l1.val < l2.val){ cur.next = l1; cur = cur.next; l1 = l1.next; } else{ cur.next = l2; cur = cur.next; l2 = l2.next; } } if(l1 == null)cur.next = l2; else cur.next = l1; return ans; } }题目:https://leetcode-cn.com/problems/move-zeroes/ 思考:循环遍历数组,设置一个标记index【表示数组中非零个数】,如果数非零,把数组往前提,这样就把所有非零数赋值(移动)完毕。
class Solution { public void moveZeroes(int[] nums) { if(nums == null || nums.length <=1) return; int index = 0; for(int i=0;i<nums.length;i++){ if(nums[i] != 0){ nums[index++] = nums[i]; } } for(int i=index;i<nums.length;i++){ nums[i] = 0; } } }题目:https://leetcode-cn.com/problems/valid-anagram/ 思考:判断两个字符串中的字符是否完全相同。
//憨憨计数比较法 class Solution { public boolean isAnagram(String s, String t) { int[] sc = new int[26]; int[] tc = new int[26]; for(char ch : s.toCharArray()){ sc[ch - 'a']++; } for(char ch : t.toCharArray()){ tc[ch-'a']++; } for(int i=0;i<26;i++){ if(sc[i] != tc[i]){ return false; } } return true; } }题目:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/ 思考:怎么说,看题解会发现是道思维题而不是算法题,可以当天抛出当天买入别的。
class Solution { public int maxProfit(int[] prices) { int ans = 0; for(int i=1;i<prices.length;i++){ if(prices[i]>prices[i-1]){ ans+=prices[i]-prices[i-1]; } } return ans; } }题目:https://leetcode-cn.com/problems/happy-number/ 思考:根据题解的快慢指针法:
如果给定的数字最后会一直循环重复,那么快的指针(值)一定会追上慢的指针(值),也就是两者一定会相等。 如果没有循环重复,那么最后快慢指针也会相等,且都等于1。
class Solution { public boolean isHappy(int n) { int fast = n; int slow = n; do{ slow = quareSum(slow); fast = quareSum(fast); fast = quareSum(fast); }while(slow != fast); if(fast==1){ return true; } else{ return false; } } private int quareSum(int m){ int sum = 0; while(m!=0){ sum+=(m%10)*(m%10); m/=10; } return sum; } }题目: 思考:只会老实人做法,循环,每次分析。
当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类 在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类
class Solution { public String countAndSay(int n) { String ans = "1"; if(n == 1)return ans; for(int i=0;i<n-1;i++){ StringBuffer s = new StringBuffer(); char t = ans.charAt(0); int count = 0; for(int j=0;j<ans.length();j++){ if(t!=ans.charAt(j)){ s.append(count); s.append(t); t=ans.charAt(j); count=1; } else{ count++; } } s.append(count); s.append(ans.charAt(ans.length()-1)); ans = s.toString(); } return ans; } }昨天由于感情问题心情不好,不想学习。
题目:https://leetcode-cn.com/problems/missing-number/ 思考:计算出如果数字不缺失时,数组的和【数列求和晓得伐,首项加尾项的和乘高除以2】,计算出此时缺失数字时的数组的和【一个循环】,两项相减得出的值就是答案。
class Solution { public int missingNumber(int[] nums) { int sum = 0; int length = nums.length; for(int i=0;i<length;i++){ sum+=nums[i];//计算数组和 } length+=1;//不缺失数字时的数组长度 int ans = (length-1)*length/2 - sum;//首项是0省略 return ans; } }题目:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/ 思考:【今天之前买入的最小值】【今天卖出的最大获利】 比较【每天的最大获利】,取最大值即可
class Solution { public int maxProfit(int[] prices) { if(prices.length<=1)return 0; int minn = prices[0]; int maxx = 0; for(int i=1;i<prices.length;i++){ maxx = Math.max(maxx,prices[i]-minn); minn = Math.min(minn,prices[i]); } return maxx; } }题目:https://leetcode-cn.com/problems/contains-duplicate/ 思考:
Set自带去重,如果去重后的长度小于原长度,则返回true
class Solution { public boolean containsDuplicate(int[] nums) { Set<Integer> res = new HashSet<>(); for(int i : nums){ res.add(i); } return res.size()<nums.length?true:false; } }题目:https://leetcode-cn.com/problems/two-sum/ 思考:利用哈希表的性质,键值对(数值,下标)
class Solution { public int[] twoSum(int[] nums, int target) { int[] index = new int[2]; HashMap<Integer,Integer> hash = new HashMap<>(); for(int i=0;i<nums.length;i++){ if(hash.containsKey(nums[i])){ index[0]=i; index[1]=hash.get(nums[i]); return index; } hash.put(target-nums[i],i); } return index; } }近段时间忙于其他事务,随机更新。
题目:https://leetcode-cn.com/problems/maximum-subarray/ 思考:讲道理这题用贪心(?比较符合我的思路,但是要按要求用分治法写我就很苦恼了(用暴力的就憨憨了)【看了分治法题解感想:可以,但是我拒绝】
//算贪心吗(?) class Solution { public: int maxSubArray(vector<int>& nums) { int ans = nums[0]; int sum = 0; for(int i=0 ;i<nums.size();i++){ if(sum > 0){ sum+=nums[i]; } else{ sum = nums[i]; } ans = max(ans,sum); } return ans; } }; //动态规划 class Solution { public: int maxSubArray(vector<int>& nums) { int ans = nums[0]; int dp[nums.size()+1]; for(int i=0;i<nums.size();i++){ dp[i] = 0; } dp[0] = nums[0]; for(int i=1;i<nums.size();i++){ dp[i]=max(dp[i-1]+nums[i],nums[i]); ans = max(dp[i],ans); } return ans; } };