Java常用的算法
1.给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
class Solution { public int search(int[] nums, int target) { int low = 0,high = nums.length-1; while(low <= high) { int mid = (low + high)/2; if(nums[mid] == target){ return mid; } else if(target > nums[mid]) { low = mid+1; } else if(nums[target < nums[mid]) { high = mid -1; } } return -1; } }
2.你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
/* The isBadVersion API is defined in the parent class VersionControl. boolean isBadVersion(int version); */ public class Solution extends VersionControl { public int firstBadVersion(int n) { int low = 1,high = n; while(low < high) { int mid = (high - low)/2+low; if(isBadVersion(mid)){ high = mid; } else { low = mid +1; } } return high; } }
3.给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
class Solution { public int searchInsert(int[] nums, int target) { int low = 0,high = nums.length-1; while(low <= high) { int mid = (high+low)/2; if(nums[mid] == target) { return mid; }else if (target > nums[mid]) { low = mid +1; } else if(target < nums[mid]) { high = mid -1; } } return low; } }
4.给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
class Solution { public int[] sortedSquares(int[] nums) { int[] nums1 = new int[nums.length]; for(int i = 0, j = nums.length-1, pos = nums.length -1; i<=j;) { if (nums[i]*nums[i] > nums[j]*nums[j]){ nums1[pos] = nums[i]*nums[i]; ++i; }else { nums1[pos] = nums[j]*nums[j]; --j; } --pos; } return nums1; } }
5.给定一个整数数组 nums,将数组中的元素向右轮转 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]
class Solution { public void rotate(int[] nums, int k) { k%=nums.length; reverse(nums,0,nums.length-1); reverse(nums,0,k-1); reverse(nums,k,nums.length-1); } public void reverse(int[] nums, int start,int end) { while(start < end) { int tmp = nums[start]; nums[start] = nums[end]; nums[end] = tmp; start++; end--; } } }
6.假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给你一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false 。
示例 1:
输入:flowerbed = [1,0,0,0,1], n = 1
输出:true
示例 2:
输入:flowerbed = [1,0,0,0,1], n = 2
输出:false
class Solution { public boolean canPlaceFlowers(int[] flowerbed, int n) { int m = 0; for (int i = 0; i < flowerbed.length;) { if (flowerbed[i] == 0) {//当前没有种花 if (i == flowerbed.length-1) {//如果当前节点时最后一个节点,可以直接种上 m++; i++; break; } if (flowerbed[i+1] == 0) {//如果下个位置没有种花,即00的情况 m++; //根据规则,此时下一个位置就没法种花,直接跳到下下个位置 i+=2; } else if (flowerbed[i+1] == 1) {//如果下个位置种花了,即010的情况 // 根据规则,当前位置不能种花,下一个位置的下一个位置也不能种花,直接跳到下下下个位置 i+=3; } }else { i+=2; } } return m>=n; } }
7.给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。
如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false 。
示例 1:
输入:nums = [1,2,3,4,5]
输出:true
解释:任何 i < j < k 的三元组都满足题意
示例 2:
输入:nums = [5,4,3,2,1]
输出:false
解释:不存在满足题意的三元组
示例 3:
输入:nums = [2,1,5,0,4,6]
输出:true
解释:三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6
public static boolean increasingTriplet(int[] nums) { int n = nums.length; if (n < 3) { return false; } int[] leftMin = new int[n]; leftMin[0] = nums[0]; for (int i = 1; i < n; i++) { leftMin[i] = Math.min(leftMin[i - 1], nums[i]); } int[] rightMax = new int[n]; rightMax[n - 1] = nums[n - 1]; for (int i = n - 2; i >= 0; i--) { rightMax[i] = Math.max(rightMax[i + 1], nums[i]); } for (int i = 1; i < n - 1; i++) { if (nums[i] > leftMin[i - 1] && nums[i] < rightMax[i + 1]) { return true; } } return false; }
public static boolean increasingTriplet(int[] nums) { int n = nums.length; if (n < 3) { return false; } int first = nums[0], second = Integer.MAX_VALUE; for (int i = 1; i < n; i++) { int num = nums[i]; if (num > second) { return true; } else if (num > first) { second = num; } else { first = num; } } return false; }
8.给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
进阶:
如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
示例 1:
输入:s = "abc", t = "ahbgdc"
输出:true
示例 2:
输入:s = "axc", t = "ahbgdc"
输出:false
class Solution { public boolean isSubsequence(String s, String t) { for (int i = 0; i < s.length(); i++) { int idx = t.indexOf(s.charAt(i)); if (idx ==-1) { return false; } else { t = t.substring(idx+1); } } return true; } }