在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是2或者3。存在不合法的输入的话输出-1;
使用HashSet的性质进行判断处理即可;
public int duplicate (int[] numbers) {
if(numbers == null || numbers.length == 0){
return -1;
}
HashSet<Integer> hashSet = new HashSet<>();
for(int num:numbers){
if(hashSet.contains(num)){
return num;
}else{
hashSet.add(num);
}
}
return -1;
}
给你一个长度为 n 的整数数组 nums ,其中 nums 的所有整数都在范围 [1, n] 内,且每个整数出现 一次 或 两次 。请你找出所有出现 两次 的整数,并以数组形式返回。
你必须设计并实现一个时间复杂度为 O(n) 且仅使用常量额外空间的算法解决此问题。
LeetCode链接
由于nums数组中的数字范围为[1-n],则我们可以将对应数字放在其对应下标位置[0~n-1],这样如果存在数字重复,则一定会有num[i]-1!=index存在,这样就可以找出重复数字。
public List<Integer> findDuplicates(int[] nums) {
List<Integer> result = new ArrayList();
for(int i = 0; i < nums.length;i++){
while(nums[i] != nums[nums[i]-1]){
swap(i,nums[i]-1,nums);
}
}
for(int i = 0; i < nums.length;i++){
if(nums[i] - 1 !=i){
result.add(nums[i]);
}
}
return result;
}
private void swap(int i,int j, int[] nums){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007
牛客题目链接
采用归并排序思想解决;
private int result;
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @return int整型
*/
public int InversePairs (int[] nums) {
if(nums == null || nums.length == 0){
return 0;
}
mergeSort(nums,0,nums.length-1);
return result ;
}
private void mergeSort(int[] nums,int l,int r){
int mid = l + (r - l) /2;
if(l < r){
mergeSort(nums,l,mid);
mergeSort(nums,mid+1,r);
merge(nums,l,mid,r);
}
}
private void merge(int[] nums,int l,int mid,int r){
int[] help = new int[r-l+1];
int i = 0;
int p1 = l;
int p2 = mid +1 ;
while(p1 <= mid && p2 <=r){
if(nums[p1] <= nums[p2]){
help[i++] = nums[p1++];
}else {
result+=mid - p1+1;
result%= 1000000007;
help[i++] = nums[p2++];
}
}
while(p1 <= mid){
help[i++] = nums[p1++];
}
while(p2 <= r){
help[i++] = nums[p2++];
}
for(int j =0;j <help.length;j++){
nums[l+j] = help[j];
}
}
设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。
示例:
输入: arr = [1,3,5,7,2,4,6,8], k = 4
输出: [1,2,3,4]
LeetCode链接
这里采用大根堆的思路来解决问题;
public int[] smallestK(int[] arr, int k) {
if(arr == null || arr.length < k){
return new int[0];
}
if(k == 0){
return new int[0];
}
PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
int[] result = new int[k];
for(int i = 0 ; i< k ; i++){
queue.offer(arr[i]);
}
for(int i = k ; i < arr.length;i++){
int peek = queue.peek();
if(arr[i] < peek){
queue.poll();
queue.offer(arr[i]);
}
}
int j = 0;
while(!queue.isEmpty()){
int num = queue.poll();
result[j++] = num;
}
return result;
}
中位数 是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
LeetCode链接
//Java优先级队列 默认小顶堆
private PriorityQueue<Integer> minQueue = new PriorityQueue();
// 定义大顶堆
private PriorityQueue<Integer> maxQueue = new PriorityQueue<>((x,y) -> (y-x));
public MedianFinder() {
}
//加入元素时
public void addNum(int num) {
if(maxQueue.size() == 0){
maxQueue.offer(num);
} else {
int peekNum = maxQueue.peek();
if(peekNum >= num){
maxQueue.offer(num);
}else{
minQueue.offer(num);
}
changeQueueSize();
}
}
public double findMedian() {
int maxSize = maxQueue.size();
if(maxSize == 0){
return 0;
}
int minSize = minQueue.size();
if(minSize == maxSize){
return (maxQueue.peek() + minQueue.peek()) / 2.0;
}
double result = maxSize > minSize ? maxQueue.peek(): minQueue.peek();
return result;
}
private void changeQueueSize(){
int maxSize = maxQueue.size();
int minSize = minQueue.size();
if(maxSize - minSize == 2){
minQueue.offer(maxQueue.poll());
}
if(minSize - maxSize == 2){
maxQueue.offer(minQueue.poll());
}
}