leetcode(daily 11-8 ~ 11-14)
leetcode 每日一题
11-8 122. 买卖股票的最佳时机 II
class Solution {
public int maxProfit(int[] prices) {
// 贪心算法:只要今天买明天赚就买入
// profit用来记录前后两天的差值
int res = 0;
int[] profit = new int[prices.length - 1];
for(int i =0;i<prices.length-1;i++) profit[i] = prices[i+1] - prices[i];
for(int n:profit) if(n>0) res+=n;
return res;
}
11-9 973. 最接近原点的 K 个点
class Solution {
public int[][] kClosest(int[][] points, int K) {
// myidea : 先实现一个计算距离的函数,计算出所有的距离,
int[][] res = new int[K][2];
int[] temp = new int[points.length];
for(int i = 0;i<points.length;i++) temp[i] = calcDis(points[i]);
Arrays.sort(temp);
int Kth = temp[K-1];
int flag = 0;
for(int i = 0;i<points.length;i++){
if(calcDis(points[i]) <= Kth){
res[flag][0] = points[i][0];
res[flag][1] = points[i][1];
flag++;
}
}
return res;
}
public int calcDis(int[] point){
return point[0] * point[0] + point[1] * point[1];
}
}
11-10 31 下一个排列
class Solution{
public void nextPermutation(int[] nums) {
// 解题思路:若想要寻找下一个较大的排列,
/**
452631 --> 45[2]631 --> 45[2]6[3]1 --> 45[3]6[2]1 --> 453126
step 1:从右至左找到第一个递减的数对 nums[i] > nums[i+1]
step 2:从右至左找到第一个比i指向的元素大的元素记为j
step 3:交换i,j位置的元素
step 4:翻转从i到末尾的元素即可
*/
int i = nums.length - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) {
i--;
}
if (i >= 0) {
int j = nums.length - 1;
while (j >= 0 && nums[i] >= nums[j]) {
j--;
}
swap(nums, i, j);
}
reverse(nums, i + 1,nums.length-1);
}
// 交换两个位置的元素
public void swap(int[] nums,int i,int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
// 翻转
public void reverse(int[] nums,int i,int j){
int left = i;
int right = j;
while(left < right){
swap(nums,left,right);
left++;
right--;
}
}
}
11-11 514 自由之路
解题思路
class Solution{
public int findRotateSteps(String ring,String key){
int n =ring.length();
int m = key.length();
// 记录ring中字母出现的位置
List<Integer>[] pos = new List[26];
for(int i = 0;i<26;i++) pos[i] = new ArrayList<Integer>();
for(int i = 0;i<n;i++) pos[ring.charAt(i) - \'a\'].add(i);
int[][] dp = new int[m][n];
for(int i = 0;i<m;i++) Arrays.fill(dp[i],Integer.MAX_VALUE);
for(int i:pos[key.charAt(0) - \'a\']) dp[0][i] = Math.min(i,n-i)+1;
for(int i = 1;i<m;i++){
for(int j:pos[key.charAt(i) - \'a\']){
for(int k:pos[key.charAt(i-1) - \'a\']){
dp[i][j] = Math.min(dp[i][j] , dp[i-1][k] + Math.min(Math.abs(j-k),n-Math.abs(j-k))+1);
}
}
}
return Arrays.stream(dp[m-1]).min().getAsInt();
}
}
11-12 922. 按奇偶排序数组 II
给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。
对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。
你可以返回任何满足上述条件的数组作为答案。
class Solution {
public int[] sortArrayByParityII(int[] A) {
// myidea : 设置两个指针即可
int i = 0;// 该指针指向的元素应该是偶数
int j = 1;// 该指针指向的元素应该是奇数
while(i<A.length && j < A.length){
while(i<A.length && A[i]%2 == 0) i+=2;
while(j<A.length && A[j]%2 == 1) j+=2;
if(i>=A.length || j>=A.length) break;
int tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
return A;
}
}
11-13 328. 奇偶链表
给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
class Solution {
public ListNode oddEvenList(ListNode head) {
if (head == null) return head;
ListNode evenHead = head.next;
ListNode odd = head, even = evenHead;
while(even!=null && even.next!=null){
odd.next = odd.next.next;
odd = odd.next;
even.next = even.next.next;
even = even.next;
}
odd.next = evenHead;
return head;
}
}
11-14 1122. 数组的相对排序
给你两个数组,arr1 和 arr2,
- arr2 中的元素各不相同
- arr2 中的每个元素都出现在 arr1 中
对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。
class Solution {
public int[] relativeSortArray(int[] arr1, int[] arr2) {
//由于arr1的可能取值为0-1000,共1001个取值,不算一个很大的取值范围,所以可以利用桶式排序
int[] bucket = new int[1001];
//计数每个桶有多少个数,也就是每个值在数组中有几个
for(int num:arr1){
bucket[num]++;
}
//由于重新排序不会改变数组的长度,所以可以利用原数组,可以节省空间复杂度
int i = 0;
//由于排序是按照相对顺序进行排序,所以,首先根据arr2中的桶的顺序,依次从对应的桶中取数到arr1中
//并注意,每拿出一个数,需要将对桶中的数的个数进行-1操作
for(int num:arr2){
while(bucket[num]-- > 0){
arr1[i++] = num;
}
}
//未在arr2中的桶中的数,按照桶号升序进行输出,所以进行二次遍历
for(int j = 0; j < 1001; ++j){
while(bucket[j]-- > 0){
arr1[i++] = j;
}
}
return arr1;
}
}