前言
零基础小白记录一下算法学习过程(虽然记录晚了)。
第一天:二分查找
-
二分查找
网址:https://leetcode.cn/problems/binary-search/给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的target,如果目标值存在返回下标,否则返回 -1。
示例1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1class Solution { public int search(int[] nums, int target) { int left = 0,right = nums.length - 1; while(left <= right){ int pivot = (left + right) / 2; if(nums[pivot] == target){ return pivot; }else if(nums[pivot] < target){ left = pivot + 1; }else if(nums[pivot] > target){ right = pivot - 1; } } return -1; } }
-
第一个错误的版本
网址:https://leetcode.cn/problems/first-bad-version/你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用
bool isBadVersion(version)
接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。示例1:
输入:n = 5, bad = 4
输出:4
示例2:
输入:n = 1, bad = 1
输出:1public class Solution extends VersionControl { public int firstBadVersion(int n) { int left = 1, right = n; while (left < right) { // 循环直至区间左右端点相同 int mid = left + (right - left) / 2; // 防止计算时溢出 if (isBadVersion(mid)) { right = mid; // 答案在区间 [left, mid] 中 } else { left = mid + 1; // 答案在区间 [mid+1, right] 中 } } // 此时有 left == right,区间缩为一个点,即为答案 return left; } }
-
搜索插入位置
网址:https://leetcode.cn/problems/search-insert-position/给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例3:
输入: nums = [1,3,5,6], target = 7
输出: 4class Solution { public int searchInsert(int[] nums, int target) { if(nums[0] > target){return 0;} if(nums[nums.length - 1] < target){return nums.length;} int left = 0; int right = nums.length - 1; while(left < right){ int pivot = (left + right) / 2; if(nums[pivot] < target){ left = pivot + 1; }else if(nums[pivot] > target){ right = pivot; }else{ return pivot; } } return left; } }
- 感觉自己写的还是不那么好,用两个if判断跳过了特殊情况,后来再看看怎么解决吧。
第二天:双指针(一)
-
有序数组的平方
网址:https://leetcode.cn/problems/squares-of-a-sorted-array/给你一个按非递减顺序排序的整数数组 nums,返回 每个数字的平方组成的新数组,要求也按非递减顺序排序。
示例1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]思路:挺简单的,将数组的各元素先进行平方,在经过冒泡排序进行排序。
class Solution { public int[] sortedSquares(int[] nums) { for(int i = 0;i < nums.length;i++){ nums[i] = nums[i] * nums[i]; } maopao(nums); return nums; } public void maopao(int[] a){ for (int i = 0; i < a.length - 1; i++) { for (int j = 0; j < a.length - 1 - i; j++) { if (a[j] > a[j + 1]) { int temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } } }
-
轮转数组
网址:https://leetcode.cn/problems/rotate-array/
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
思路:感觉不好想可能就是这个取余的操作吧。示例1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]思路:感觉还是比较简单的吧。
class Solution { public void rotate(int[] nums, int k) { if(nums.length == 1){ nums = nums; }else{ k = k % nums.length; int[] temp = new int[k]; for(int i = 0;i < temp.length;i++){ temp[i] = nums[i + nums.length - k]; } for(int i = nums.length - 1;i >= k;i--){ nums[i] = nums[i - k]; } for(int i = 0;i < k;i++){ nums[i] = temp[i]; } } } }
第三天:双指针(二)
-
移动零
网址:https://leetcode.cn/problems/move-zeroes/给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例2:
输入: nums = [0]
输出: [0]class Solution { public void moveZeroes(int[] nums) { for(int i = 0;i < nums.length - 1;i++){ for(int j = 0;j < nums.length - 1 - i;j++){ if(nums[j] == 0){ int temp = nums[j]; nums[j] = nums[j+1]; nums[j+1] = temp; } } } } }
-
两数之和 II - 输入有序数组
网址:https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
示例1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
示例2:
输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
示例3:
输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。思路:主要还是双指针的思想吧。
class Solution { public int[] twoSum(int[] numbers, int target) { int[] ans = new int[2]; int i = 0; int j = numbers.length - 1; while(i < j){ if((numbers[i] + numbers[j]) == target){ ans[0] = i + 1; ans[1] = j + 1; return ans; }else if((numbers[i] + numbers[j]) < target){ i++; }else if((numbers[i] + numbers[j]) > target){ j--; } } return ans; } }
第四天:双指针(三)
-
反转字符串
网址:https://leetcode.cn/problems/reverse-string/
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
示例 1:
输入:s = [“h”,“e”,“l”,“l”,“o”]
输出:[“o”,“l”,“l”,“e”,“h”]
示例 2:
输入:s = [“H”,“a”,“n”,“n”,“a”,“h”]
输出:[“h”,“a”,“n”,“n”,“a”,“H”]思路:主要还是双指针吧。
class Solution { public void reverseString(char[] s) { int i = 0,j = s.length - 1; while(i < j){ char temp = s[i]; s[i] = s[j]; s[j] = temp; i++; j--; } } }
-
反转字符串中的单词 III
网址:https://leetcode.cn/problems/reverse-words-in-a-string-iii/
给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。示例 1:
输入:s = “Let’s take LeetCode contest”
输出:“s’teL ekat edoCteeL tsetnoc”
示例 2:
输入: s = “God Ding”
输出:“doG gniD”class Solution { public String reverseWords(String s) { String[] temp = s.split(" "); for(int i = 0;i < temp.length;i++){ String a=""; for(int j = temp[i].length() - 1;j >= 0;j--){ a+=temp[i].charAt(j); } temp[i] = a; } String ans=""; for(int i = 0;i < temp.length;i++){ ans+=temp[i]; if(i == temp.length - 1){ break; }else{ ans+=" "; } } return ans; } }
第五天:双指针(四)
-
链表的中间结点
网址:https://leetcode.cn/problems/middle-of-the-linked-list/给定一个头结点为 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。class Solution { public ListNode middleNode(ListNode head) { ListNode i = head; ListNode j = head; while(j != null && j.next != null){ i = i.next; j = j.next.next; } return i; } }
-
删除链表的倒数第 N 个结点
网址:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { if(head.next == null){return head.next;} ListNode temp = new ListNode(0,head); ListNode i = temp; ListNode j = head; for(int c = 0;c < n;c++){ j = j.next; } while(j != null){ i = i.next; j = j.next; } i.next = i.next.next; return temp.next; } }
总结
慢慢写吧,认识到自己很菜的事实了😭。思路还得想想怎么整理一下。