如果有错的还请各位大佬指出呀
有些是copy的还望不要介意
本人只做学习记录
题目描述:
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
测试用例的答案是一个 32-位 整数。
子数组 是数组的连续子序列。
示例:
输入: nums = [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
class Solution {
public int maxProduct(int[] nums) {
int max = Integer.MIN_VALUE,mx = 1,mi = 1;
for(int i=0;i<nums.length;i++){
//出现负数时,会导致大的变小,小的变大
//mx=6 6*(-2)=-12 mi=3 3*(-2)=-6
//所以先交换mx和mi再进行计算
//这也是为什么要维护mi的原因
if(nums[i]<0){
int temp = mx;
mx = mi;
mi = temp;
}
mx = Math.max(mx*nums[i],nums[i]);
mi = Math.min(mi*nums[i],nums[i]);
max = Math.max(max,mx);
}
return max;
}
}
题目描述:
给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例:
输入:nums = [2,2,1,1,1,2,2]
输出:2
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
}
class Solution {
public int majorityElement(int[] nums) {
//先假设第一个数是众数,票数为1
int num = nums[0],count = 1;
for(int i=1;i<nums.length;i++){
//与假设的众数值相同则票数+1
if(num == nums[i]){
count++;
}else{
//值不同则-1
count--;
//若此时票数为0了,则替换众数
if(count==0){
num = nums[i];
count = 1;
}
}
}
//因为存在多数元素,所以每个众数元素与其他元素进行抵消,剩下的便是众数
return num;
}
}
题目描述:
给你一个数组,将数组中的元素向右轮转 `k` 个位置,其中 `k` 是非负数
示例:
输入: 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) {
int n = nums.length;
//防止原本的数丢失
int[] newNums = new int[n];
for(int i = 0;i<n;i++){
//k可能大过n
newNums[(i+k)%n] = nums[i];
}
//深拷贝,源数组,原数组起始位置,目标数组,目标数组起始位置,复制的元素数量
System.arraycopy(newNums,0,nums,0,n);
}
}
进阶:
尽可能想出更多的解决方案,至少有 **三种** 不同的方法可以解决这个问题。
你可以使用空间复杂度为 `O(1)` 的 **原地** 算法解决这个问题吗?
class Solution {
public void rotate(int[] nums, int k) {
//k可能大于n,直接取余可以获取最终位置
k = k%nums.length;
//先将整个数组反转
reverse(nums,0,nums.length-1);
//以k为切割分别反转
reverse(nums,0,k-1);
reverse(nums,k,nums.length-1);
}
private void reverse(int[] nums,int i,int j){
while(i<j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
i++;
j--;
}
}
}
题目描述:
给你一个整数数组 `nums` 。如果任一值在数组中出现 **至少两次** ,返回 `true` ;如果数组中每个元素互不相同,返回 `false` 。
示例:
输入:nums = [1,2,3,1]
输出:true
class Solution {
public boolean containsDuplicate(int[] nums) {
Arrays.sort(nums);
int n = nums.length;
for(int i=0;i<n-1;i++){
//排好序后相邻的相等
if(nums[i] == nums[i+1]){
return true;
}
}
return false;
}
}
class Solution {
public boolean containsDuplicate(int[] nums) {
Set<Integer> set = new HashSet<>();
for(int i=0;i<nums.length;i++){
//hashset如果插入已存在的元素则会返回false
if(!set.add(nums[i])){
return true;
}
}
return false;
}
}
题目描述:
给定一个数组 `nums`,编写一个函数将所有 `0` 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
进阶: 你能尽量减少完成的操作次数吗?
代码实现
时间O(n)空间O(1)
class Solution {
public void moveZeroes(int[] nums) {
if(nums == null){
return;
}
int i=0,j = 0;
for(;i<nums.length;i++){
if(nums[i] != 0){
int temp = nums[i];
nums[i] = nums[j];
nums[j++] = temp;
}
}
}
}
题目描述:
给你一个整数数组 nums ,设计算法来打乱一个没有重复元素的数组。打乱后,数组的所有排列应该是 等可能 的。
实现 Solution class:
Solution(int[] nums) 使用整数数组 nums 初始化对象
int[] reset() 重设数组到它的初始状态并返回
int[] shuffle() 返回数组随机打乱后的结果
示例:
输入
["Solution", "shuffle", "reset", "shuffle"]
[[[1, 2, 3]], [], [], []]
输出
[null, [3, 1, 2], [1, 2, 3], [1, 3, 2]]
解释
Solution solution = new Solution([1, 2, 3]);
solution.shuffle(); // 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。例如,返回 [3, 1, 2]
solution.reset(); // 重设数组到它的初始状态 [1, 2, 3] 。返回 [1, 2, 3]
solution.shuffle(); // 随机返回数组 [1, 2, 3] 打乱后的结果。例如,返回 [1, 3, 2]
class Solution {
int[] nums;
int[] tnums;
public Solution(int[] nums) {
this.nums = nums;
this.tnums = new int[nums.length];
//调用java内存模型中本地方法栈区
System.arraycopy(nums,0,tnums,0,nums.length);
}
public int[] reset() {
return tnums;
}
public int[] shuffle() {
//洗牌算法
Random random = new Random();
int n = nums.length;
for(int i=0;i<n;i++){
int j = i+random.nextInt(n - i);
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
return nums;
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(nums);
* int[] param_1 = obj.reset();
* int[] param_2 = obj.shuffle();
*/
题目描述:
给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
示例:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
进阶:
如果给定的数组已经排好序呢?你将如何优化你的算法?
如果 nums1 的大小比 nums2 小,哪种方法更优?
如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
哈希表
时间O(m+n)空间O(min(m,n))
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
if(nums1.length > nums2.length){
intersect(nums2,nums1);
}
Map<Integer,Integer> map = new HashMap<>();
for(int num:nums1){
int count = map.getOrDefault(num,0) + 1;
map.put(num,count);
}
int[] temp = new int[nums1.length];
int index = 0;
for(int num:nums2){
int count = map.getOrDefault(num,0);
if(count > 0){
temp[index++] = num;
count--;
if(count > 0){
map.put(num,count);
}else{
map.remove(num);
}
}
}
return Arrays.copyOfRange(temp,0,index);
}
}
双指针
时间O(mlogm+nlogn),空间O(min(m,n))
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
int length1 = nums1.length,length2 = nums2.length;
int[] temp = new int[Math.min(length1,length2)];
int i = 0,j = 0,index = 0;
while(i<length1 && j<length2){
//两个元素不相等则小的那个指针右移动
if(nums1[i] < nums2[j]){
i++;
}else if(nums1[i] > nums2[j]){
j++;
}else if(nums1[i] == nums2[j]){
//相等则添加,并指针都右移
temp[index] = nums1[i];
index++;
i++;
j++;
}
}
return Arrays.copyOfRange(temp,0,index);
}
}
题目描述:
给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。
如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false 。
示例:
输入:nums = [1,2,3,4,5]
输出:true
解释:任何 i < j < k 的三元组都满足题意
进阶: 你能实现时间复杂度为 O(n)
,空间复杂度为 O(1)
的解决方案吗?
贪心
时间O(n)空间O(1)
class Solution {
public boolean increasingTriplet(int[] nums) {
int f = nums[0],s = Integer.MAX_VALUE;
int n = nums.length;
if(n < 3){
return false;
}
//保证第二个值比第一个值大,此时只要找到第三个数便可
for(int i=1;i<n;i++){
if(nums[i] > s){
//如果第三个数比第二个数大则满足
return true;
}else if(nums[i] > f){
//比第二个数小比第一个数大则将该值赋给第二个数,继续找第三个数
s = nums[i];
}else{
//比第一个数小则将该值赋给第一个数,此时新的第一个值就在旧第二个值前面
f = nums[i];
}
}
return false;
}
}
题目描述:
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
输入:matrix = [[1,4,7,11,15],
[2,5,8,12,19],
[3,6,9,16,22],
[10,13,14,17,24],
[18,21,23,26,30]], target = 5
输出:true
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int row = matrix.length - 1;
int col = matrix[0].length;
int temp=0;
while(row>=0 || temp<=col-1){
if(matrix[row][temp] == target){
return true;
}else if(matrix[row][temp] < target){
temp++;
if(temp > col-1) return false;
}else if(matrix[row][temp] > target){
row--;
if(row < 0) return false;
}
}
return false;
}
}
题目描述:
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请不要使用除法,且在 O(n) 时间复杂度内完成此题
进阶:你可以在 O(1)
的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组**不被视为额外空间。)
示例:
输入: nums = [1,2,3,4]
输出: [24,12,8,6]
class Solution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] answer = new int[n];
int l=1,r = 1;
for(int i=0;i<n;i++){
answer[i] = l;
l *= nums[i];
}
for(int i = n-1;i>0;i--){
r *= nums[i];
//该位置的值等于左边所有的元素乘积乘以右边所有元素的乘积
answer[i-1] *= r;
}
return answer;
}
}