算法练习-排序(二)
创始人
2024-05-28 18:16:43
0

算法练习-排序(二)

文章目录

  • 算法练习-排序(二)
    • 1 合并排序的数组
      • 1.1 题目
      • 1.2 题解
    • 2 有效的字母异位词
      • 2.1 题目
      • 2.2 题解
    • 3 判断能否形成等差数列
      • 3.1 题目
      • 3.2 题解
    • 4 合并区间
      • 4.1 题目
      • 3.2 题解
    • 5 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
      • 5.1 题目
      • 5.2 题解
    • 6 颜色分类
      • 6.1 题目
      • 6.2 题解
    • 7 最小k个数
      • 7.1 题目
      • 7.2 题解
    • 8 排序链表
      • 8.1 题目
      • 8.2 题解
        • 8.2.1 递归解法
        • 8.2.2 非递归解法
    • 9 剑指 Offer 51. 数组中的逆序对(hard)
      • 9.1 题目
      • 9.2 题解
        • 9.2.1 暴力(超时)
        • 9.2.2 逆序度

1 合并排序的数组

链接:https://leetcode.cn/problems/sorted-merge-lcci

1.1 题目

给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。

初始化 A 和 B 的元素数量分别为 m 和 n。

示例:

输入:
A = [1,2,3,0,0,0], m = 3
B = [2,5,6], n = 3

输出: [1,2,2,3,5,6]
说明:

A.length == n + m

1.2 题解

class Solution {public void merge(int[] A, int m, int[] B, int n) {int k = m + n - 1;int i = m - 1;int j = n - 1;while (i >= 0 && j >= 0) {if (A[i] >= B[j]) {A[k--] = A[i];i--;} else {A[k--] = B[j];j--;}}while (i >= 0) {A[k--] = A[i--];}while (j >= 0) {A[k--] = B[j--];}}
}

2 有效的字母异位词

链接:https://leetcode.cn/problems/valid-anagram

2.1 题目

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例 1:

输入: s = “anagram”, t = “nagaram”
输出: true
示例 2:

输入: s = “rat”, t = “car”
输出: false

提示:

1 <= s.length, t.length <= 5 * 104
s 和 t 仅包含小写字母

2.2 题解

class Solution {public boolean isAnagram(String s, String t) {if (s.length() != t.length()) {return false;}char[] str1 = s.toCharArray();char[] str2 = t.toCharArray();Arrays.sort(str1);Arrays.sort(str2);for (int i = 0; i < str1.length; i++) {if (str1[i] != str2[i]) {return false;}}return true;}
}

3 判断能否形成等差数列

链接:https://leetcode.cn/problems/can-make-arithmetic-progression-from-sequence

3.1 题目

给你一个数字数组 arr 。

如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列 。

如果可以重新排列数组形成等差数列,请返回 true ;否则,返回 false 。

示例 1:

输入:arr = [3,5,1]
输出:true
解释:对数组重新排序得到 [1,3,5] 或者 [5,3,1] ,任意相邻两项的差分别为 2 或 -2 ,可以形成等差数列。
示例 2:

输入:arr = [1,2,4]
输出:false
解释:无法通过重新排序得到等差数列。

提示:

2 <= arr.length <= 1000
-10^6 <= arr[i] <= 10^6

3.2 题解

class Solution {public boolean canMakeArithmeticProgression(int[] arr) {Arrays.sort(arr);int diff = arr[1] - arr[0];for (int i = 2; i < arr.length; i++) {if (arr[i] - arr[i - 1] != diff) {return false;}}return true;}
}

4 合并区间

链接:https://leetcode.cn/problems/merge-intervals

4.1 题目

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

3.2 题解

class Solution {public int[][] merge(int[][] intervals) {Arrays.sort(intervals, new Comparator() {public int compare(int[] interval1, int[] interval2) {return interval1[0] - interval2[0];}});List result = new ArrayList<>();int curLeft = intervals[0][0];int curRight = intervals[0][1];for (int i = 1; i < intervals.length; ++i) {if (intervals[i][0] <= curRight) {if (intervals[i][1] > curRight) {curRight = intervals[i][1];}} else {result.add(new int[]{curLeft, curRight});curLeft = intervals[i][0];curRight = intervals[i][1];}}result.add(new int[]{curLeft, curRight});return result.toArray(new int[result.size()][]);}
}

5 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

链接:https://leetcode.cn/problems/diao-zheng-shu-zu-shun-xu-shi-qi-shu-wei-yu-ou-shu-qian-mian-lcof

5.1 题目

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。

示例:

输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。

提示:

0 <= nums.length <= 50000
0 <= nums[i] <= 10000

5.2 题解

class Solution {public int[] exchange(int[] nums) {int i = 0;int j = nums.length - 1;while (i < j) {if (nums[i] % 2 == 1) {i++;continue;}if (nums[j] % 2 == 0) {j--;continue;}int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;i++;j--;}return nums;}
}

6 颜色分类

链接:https://leetcode.cn/problems/sort-colors

6.1 题目

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库内置的 sort 函数的情况下解决这个问题。

示例 1:

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
示例 2:

输入:nums = [2,0,1]
输出:[0,1,2]

提示:

n == nums.length
1 <= n <= 300
nums[i] 为 0、1 或 2

6.2 题解

class Solution {public void sortColors(int[] nums) {int p = 0;int q = nums.length - 1;while (p < q) {if (nums[p] != 2) {p++;continue;}if (nums[q] == 2) {q--;continue;}swap(nums, p, q);p++;q--;}int i = 0;int j = p;if (nums[j] == 2) j--;while (i < j) {if (nums[i] == 0) {i++;continue;}if (nums[j] == 1) {j-;continue;}swap(nums, i, j);i++;j--;}}private void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;} 
}

7 最小k个数

链接:https://leetcode.cn/problems/smallest-k-lcci

7.1 题目

设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。

示例:

输入: arr = [1,3,5,7,2,4,6,8], k = 4
输出: [1,2,3,4]
提示:

0 <= len(arr) <= 100000
0 <= k <= min(100000, len(arr))

7.2 题解

class Solution {int[] result;int count = 0;public int[] smallestK(int[] arr, int k) {if (k == 0 || arr.length < k) return new int[0];result = new int[k];quickSort(arr, 0 , arr.length - 1, k);return result;}private void quickSort(int[] nums, int p, int r, int k) {if (p > r) return;int q = partition(nums, p, r);if (q - p + 1 == k) {for (int i = p; i <= q; ++i) {result[count++] = nums[i];}} else if (q - p + 1 < k) {for (int i = p; i <= q; ++i) {result[count++] = nums[i];}quickSort(nums, q + 1, r, k - (q - p + 1));} else {quickSort(nums, p, q - 1, k);}}private int partition(int[] nums, int p, int r) {int i = p - 1;int j = p;while (j < r) {if (nums[j] < nums[r]) {swap(nums, j, i + 1);i++;}j++;}swap(nums, i + 1, r);return i + 1;}private void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}}

8 排序链表

8.1 题目

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表

**进阶:**你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

8.2 题解

8.2.1 递归解法

class Solution {public ListNode sortList(ListNode head) {if (head == null) return null;if (head.next == null) return head;ListNode midNode = findMidNode(head);ListNode nextNode = midNode.next;midNode.next = null;ListNode leftNode = sortList(head);ListNode rightNode = sortList(nextNode);return mergeList(leftNode, rightNode);}private ListNode findMidNode(ListNode head) {ListNode slow = head;ListNode fast = head;while (fast.next != null && fast.next.next != null) {fast = fast.next.next;slow = slow.next;}return slow;}private ListNode mergeList(ListNode headA, ListNode headB) {ListNode newHead = new ListNode();ListNode tail = newHead;ListNode pa = headA;ListNode pb = headB;while (pa != null && pb != null) {if (pa.val <= pb.val) {tail.next = pa;tail = tail.next;pa = pa.next;} else {tail.next = pb;tail = tail.next;pb = pb.next;}}if (pa != null) tail.next = pa;if (pb != null) tail.next = pb;return newHead.next;}
}

8.2.2 非递归解法

class Solution {
public ListNode sortList(ListNode head) { int n = len(head);int step = 1;while (step < n) {ListNode newHead = new ListNode(); // 结果链表ListNode tail = newHead;ListNode p = head;while (p != null) {// [p, q]ListNode q = p;int count = 1;while (q != null && count < step) {q = q.next;count++;}if (q == null || q.next == null) {//这⼀轮合并结束了tail.next = p;break;}//[q+1, r]ListNode r = q.next;count = 1;while (r != null && count < step) {r = r.next;count++;}// 保存下⼀个step的起点ListNode tmp = null;if (r != null) {tmp = r.next;}// merge[p, q][q+1, r]ListNode[] headAndTail = merge(p, q, r);tail.next = headAndTail[0];tail = headAndTail[1];p = tmp;}head = newHead.next;step *= 2;}return head;}private int len(ListNode head) {if (head == null) return 0;int n = 1;ListNode p = head;while (p != null) {n++;p = p.next;}return n;}private ListNode[] merge(ListNode p, ListNode q, ListNode r) {ListNode newHead = new ListNode();ListNode tail = newHead;ListNode pa = p;ListNode pb = q.next;q.next = null;if (r != null) {r.next = null;}while (pa != null && pb != null) {if (pa.val <= pb.val) {tail.next = pa;tail = tail.next;pa = pa.next;} else {tail.next = pb;tail = tail.next;pb = pb.next;}}if (pa != null) {tail.next = pa;tail = q;}if (pb != null) {tail.next = pb;tail = r;}return new ListNode[]{newHead.next, tail};}
}

9 剑指 Offer 51. 数组中的逆序对(hard)

链接:https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof

9.1 题目

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

示例 1:

输入: [7,5,6,4]
输出: 5

限制:

0 <= 数组长度 <= 50000

9.2 题解

9.2.1 暴力(超时)

class Solution {public int reversePairs(int[] nums) {int count = 0;for (int i = 0; i < nums.length; i++) {int value = nums[i];for (int j = i + 1; j < nums.length; j++) {if (value > nums[j]) {count++;}}}return count;}
}

9.2.2 逆序度

逆序对个数=逆序度,排序的过程是不断减小逆序度的过程,在排序过程中,记录每步操作逆序度降低的个数,累加起来就能得到原始数据的逆序度

class Solution {int reverseCount = 0;public int reversePairs(int[] nums) {mergeSort(nums, 0, nums.length - 1);return reverseCount;}private void mergeSort(int[] nums, int p, int r) {if (p >= r) return;int q = (p + r) / 2;mergeSort(nums, p, q);mergeSort(nums, q + 1, r);merge(nums, p, q, r);}private int merge(int[] nums, int p, int q, int r) {int[] tmp = new int[r - p + 1];int i = p;int j = q + 1;int k = 0;while (i <= q && j <= r) {if (nums[j] < nums[i]) {reverseCount += (q - i + 1);tmp[k++] = nums[j];j++;} else {tmp[k++] = nums[i];i++;}}while (j <= r) {tmp[k++] = nums[j];j++;}while (i <= q) {tmp[k++] = nums[i];i++;}for (i = 0; i < r - p + 1; ++i) {nums[i + p] = tmp[i];}return reverseCount;}
}

相关内容

热门资讯

圆的作文250字 圆的作文250字  今天,我们的朱老师教我们学圆的联想,有很多很多......  0——盘子,能帮人...
写母爱让我感动的作文400字 关于写母爱让我感动的作文400字集锦9篇  在日常学习、工作和生活中,大家总免不了要接触或使用作文吧...
泥土的味道作文600字 泥土的味道作文600字(通用12篇)  在学习、工作或生活中,说到作文,大家肯定都不陌生吧,通过作文...
拖地作文 拖地作文300字(精选10篇)  在平日的学习、工作和生活里,大家对作文都不陌生吧,作文是经过人的思...
神州12号飞吧作文 神州12号飞吧作文  在学习、工作、生活中,大家或多或少都会接触过作文吧,作文是一种言语活动,具有高...
可恶的蚊子作文 可恶的蚊子作文(通用31篇)  在平时的学习、工作或生活中,大家或多或少都会接触过作文吧,作文是经过...
找春天作文 找春天作文找春天作文1  清晨,小鸟叽叽喳喳地叫着,我被小鸟叫醒了。  于是,我赶紧起来,穿好衣服,...
中国发展作文 关于中国发展作文800字(精选7篇)  在生活、工作和学习中,说到作文,大家肯定都不陌生吧,作文根据...
说句心里话作文600字 说句心里话作文600字(通用40篇)  在学习、工作乃至生活中,大家都写过作文,肯定对各类作文都很熟...
浪费粮食作文 浪费粮食作文范文(通用5篇)  无论是在学校还是在社会中,大家对作文都再熟悉不过了吧,作文是人们以书...
描写北京故宫的作文500字 描写北京故宫的作文范文500字(通用52篇)  无论是在学校还是在社会中,大家总少不了接触作文吧,写...
我和我的家作文 我和我的家作文(精选20篇)  无论是在学校还是在社会中,大家都经常看到作文的身影吧,作文是人们以书...
美丽的蝴蝶作文 美丽的蝴蝶作文美丽的蝴蝶今天,我想大家介绍一位新朋友蝴蝶。它长得可好看了,两片扇形的翅膀,有蓝色的、...
元旦的作文500字 元旦的作文500字锦集5篇  在学习、工作或生活中,大家都有写作文的经历,对作文很是熟悉吧,作文可分...
飘在天上的日子作文 飘在天上的日子作文7篇  在平日的学习、工作和生活里,大家或多或少都会接触过作文吧,写作文可以锻炼我...
一个急性子的人700字作文 一个急性子的人700字作文  我的爸爸是一个急性王,怎么这样说呢?让我慢慢道来吧。  就拿去千山的那...
爱护草坪作文 爱护草坪作文爱护草坪作文1爱护草坪一天,有三个小朋友在草坪上踢足球,这时一个小姐姐走过来说:“你们在...
最美的声音作文800字 最美的声音作文800字  世界上最美的声音是什么?这个问题,值得我们去思考,去探索一般,到底什么样是...
小象的名片 小象的名片小象的名片正文:               小象的名片    在一个森林里,好多动物都有...
蓝色的梦想作文 蓝色的梦想作文海像梦一样把我蓝色的梦想冲去。风像气一样把我美丽的神话打开。梦,我有一个渺小而孤独的蓝...