数组的题目

目录

滑动窗口

最小覆盖子串

长度最小的子数组

水果成篮

在排序数组中查找元素的第一个和最后一个位置

按奇偶顺序排序数组

搜索旋转排序数组

字符串相加

合并区间

寻找两个正序数组的中位数

统计素数个数

三个数最大乘积

排序数组的两个数之和

 向数组中追加K个整数 

旋转数组 

轮转数组 

找旋转数组的最小值

快慢指针

删除有序数组中重复项

移动零

比较含退格的字符串

有序数组的平方 

把数组所有B放左边,G放右边

寻找中心数组的中心下标


滑动窗口

无重复字符最长子串

class Solution {
    public int lengthOfLongestSubstring(String s) {
        HashMap<Character,Integer>hm=new HashMap();
        //字符,索引
        int left=0;
        int len=0;
        for(int i=0;i<s.length();i++){
            if(hm.containsKey(s.charAt(i))){
                left=Math.max(left,hm.get(s.charAt(i))+1);
            }
            hm.put(s.charAt(i),i);
            len=Math.max(len,i-left+1);  
        }
        return len;
    }
}

最小覆盖子串

class Solution {
    public String minWindow(String s, String t) {
        //我有的
        Map<Character,Integer> window = new HashMap();  // 用来记录窗口中的字符和数量
        Map<Character,Integer> need = new HashMap();  // 需要凑齐的字符和数量
        // 构建need字符集
        for (int i = 0; i < t.length(); i++) {
            char needChar = t.charAt(i);
            need.put(needChar,need.getOrDefault(needChar,0)+1);
        }
         int left = 0,right = 0,valid = 0;
        // valid是用来记录窗口中满足need要求的字符的数目,比如need中要求字符a数量为2,如果window中的a字符的数量等于了2,valid就+1,反之-1
        int len = Integer.MAX_VALUE;  // 记录最小字串的长度
        int start = 0;  // 记录最小字串的起始位置
        while(right < s.length()){
            char addChar = s.charAt(right);  // 即将要加入window的字符
            window.put(addChar,window.getOrDefault(addChar,0) + 1);  
            right++;
            // 如果加入的字符是need中要求的字符,并且数量已经达到了need要求的数量,则valid+1
            // 这里和下面都有个坑,window.get(addChar)和need.get(addChar)返回的都是对象,最好用.equals()方法比较大小
            if(need.containsKey(addChar) && window.get(addChar).equals(need.get(addChar))){
                valid++;
            }
			// 当window中记录的字符和数量满足了need中要求的字符和数量,考虑缩窗口
            while(valid == need.size()){
                // 先判断当前的最小覆盖字串是否比之前的最小覆盖字串短
                if(right - left < len){  // 注意,这里上面已经对right实施了++操作,所以这里的长度不是right - left + 1
                    len = right - left ;
                    start = left;  // 如果最短,则记录下该最小覆盖字串的起始位置
                }
                char removeChar = s.charAt(left);
                // 开始缩减窗口,left右移,如果要从window删除的字符正好是need中需要的并且,数目也等于need中需要的数目,则删减后,该该字符要求的数量显然不满足need要求的数量,所以valid要-1;
                if(need.containsKey(removeChar) && window.get(removeChar).equals(need.get(removeChar))){
                    valid--;
                }
                window.put(removeChar,window.get(removeChar) - 1);
                left++;
            }

        }
        return len == Integer.MAX_VALUE?"":s.substring(start,start+len);
    }
}

长度最小的子数组

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left=0;
        int sum=0;
        int res=65536;
        for(int i=0;i<nums.length;i++){
            sum+=nums[i];
            while(sum>=target){
                sum-=nums[left];
                res=Math.min(res,i-left+1);
                left++;
            }
        }
        if(res==65536) res=0;
        return res;
    }
}

水果成篮

class Solution {
    public int totalFruit(int[] fruits) {
        int n = fruits.length;
        Map<Integer, Integer> cnt = new HashMap<Integer, Integer>();
        int left = 0, ans = 0;
        for (int right = 0; right < n; ++right) {
            cnt.put(fruits[right], cnt.getOrDefault(fruits[right], 0) + 1);
            while (cnt.size() > 2) {
                cnt.put(fruits[left], cnt.get(fruits[left]) - 1);
                if (cnt.get(fruits[left]) == 0) {
                    cnt.remove(fruits[left]);
                }
                ++left;
            }
            ans = Math.max(ans, right - left + 1);
        }
        return ans;
    }
}

在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。

class Solution {
    public int[] searchRange(int[] nums, int target) {
        if(nums.length==0)return new int[]{-1,-1};
        if(nums.length==1){
            if(nums[0]==target)return new int[]{0,0};
            if(nums[0]!=target)return new int[]{-1,-1};
        }
        int res[]=new int[]{-1,-1};
        int left=getLeft(nums,target);
        int right=getRight(nums,target);
        res[0]=left;res[1]=right;
        return res;
    }
    public int getLeft(int[] nums, int target){
        int left=0;int right=nums.length-1;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]>=target){
                right=mid-1;
            }else{
                left=mid+1;  
            }
        }
        if(right<nums.length-1&&nums[right+1]==target)return right+1;
        return -1;
    }
    public int getRight(int[] nums, int target){
        int left=0;int right=nums.length-1;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]<=target){
                left=mid+1;
            }else{
                right=mid-1;  
            }
        }
        if(left>0&&nums[left-1]==target)return left-1;
        return -1;
    }
}

按奇偶顺序排序数组

class Solution {
    public int[] sortArrayByParityII(int[] nums) {
        int odd=1;int oven=0;
        while(odd<nums.length&&oven<nums.length){
            if(nums[odd]%2==0&&nums[oven]%2==1){
                int tmp=nums[odd];
                nums[odd]=nums[oven];
                nums[oven]=tmp;
                odd+=2;oven+=2;
            }
            else if(nums[odd]%2==0&&nums[oven]%2==0){
                oven+=2;
            }else if(nums[odd]%2==1&&nums[oven]%2==1){
                odd+=2;
            }else{
                odd+=2;oven+=2;
            }
        }
        return nums;
    }
}

搜索旋转排序数组

class Solution {
    public int search(int[] nums, int target) {
        //旋转后的数组一定是由一个有序数组组成,一个无序数组组成
        //有序数组用二分查找,无序数组继续拆分
        //index旋转点右边那个点,即数组最小值
        int index=find(nums);
        System.out.println(index);
        
        if(nums[0]<=target){//左边有序
            if(index==0){//严格单增
                return binary(nums,target,0,nums.length-1);
            }
            return binary(nums,target,0,index);
        }else{
            if(index==nums.length-1)//严格单减
            {
                for(int i=0;i<nums.length;i++){
                    if(nums[i]==target)
                        return i;
                }
            } 
            return binary(nums,target,index,nums.length-1);
        }
    }
    //找到旋转点
    public int find(int nums[]){
        int lo = 0, hi = nums.length-1;
        while(lo < hi) {
            int mid = lo+(hi-lo)/2;
            if(nums[mid] > nums[hi])
                lo = mid+1;
            else if(nums[mid] < nums[hi])
                hi = mid;
            else
                hi--;
        }
        return lo;
    }
    //二分查找
    public int binary(int nums[],int target,int left,int right){
        while(left<=right){
            int mid=(left+right)/2;
            if(nums[mid]==target){
                return mid;
            }else if(nums[mid]<target){
                left=mid+1;
            }else if(nums[mid]>target){
                right=mid-1;
            }
        }
        return -1;
    }
    
}

字符串相加

class Solution {
    public String addStrings(String num1, String num2) {
        StringBuilder sb=new StringBuilder();
        int sum=0;
        int i=num1.length()-1;int j=num2.length()-1;
        for(;i>=0||j>=0;i--,j--){
            if(i>=0){
                sum+=num1.charAt(i)-'0';
            }
            if(j>=0){
                sum+=num2.charAt(j)-'0';
            }
            sb.append(sum%10);
            sum/=10;
        }
        return sb.reverse().toString();
    }
}

合并区间

class Solution {
    public int[][] merge(int[][] intervals) {
        ArrayList<int[]> list = new ArrayList<>();
        Arrays.sort(intervals, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[0] - o2[0];
            }
        });
        int margin = intervals[0][1];
        int start = intervals[0][0];
        for (int i = 1; i < intervals.length; i++) {
            if(intervals[i][0] <= margin){
                //可以合并区间,但是还不能加进答案里,后面可能还有可能能合并的区间
                margin = Math.max(margin, intervals[i][1]);
            }
            else{
                //不能再合并了,将之前的答案加入list,更新新的起始区间
                list.add(new int[]{start, margin});
                start = intervals[i][0];
                margin = intervals[i][1];
            }
        }
        //全部都能合并 或者数目为一的情况
        list.add(new int[]{start, margin});
        return list.toArray(new int[list.size()][2]);
    }
}

寻找两个正序数组的中位数

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        PriorityQueue<Integer> SmallRootHeap = new PriorityQueue<>(new SmallRootHeapComparator());  // 小根堆
        PriorityQueue<Integer> BigRootHeap = new PriorityQueue<>(new BigRootHeapComparator());    // 大根堆

        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < nums1.length; i++) {
            list.add(nums1[i]);
        }
        for (int i = 0; i < nums2.length; i++) {
            list.add(nums2[i]);
        }
        //维护小根堆只比大根堆最多只能多1个数
        NumberOfMaintainedData(list,SmallRootHeap,BigRootHeap);
        if (list.size() % 2 == 0) {
            return (SmallRootHeap.poll() + BigRootHeap.poll()) / 2;
        }
        return BigRootHeap.poll();
    }
    private static void NumberOfMaintainedData(ArrayList<Integer> list, PriorityQueue<Integer> smallRootHeap,
            PriorityQueue<Integer> bigRootHeap) {
        for (int i = 0; i < list.size(); i++) {
            if(smallRootHeap.size() == 0 && bigRootHeap.size() == 0){
                bigRootHeap.add(list.get(i));
                continue;
            }
            while(smallRootHeap.size() - bigRootHeap.size() > 1){ // 说明smallRootHeap中的数据较为多
                bigRootHeap.add(smallRootHeap.poll());
            }
            while(bigRootHeap.size() - smallRootHeap.size() > 1){ // 说明bigRootHeap中的数据较为多
                smallRootHeap.add(bigRootHeap.poll());
            }
            if (Math.abs(smallRootHeap.size() - bigRootHeap .size())<=1) {
                bigRootHeap.add(list.get(i));
            }
        }
    }

    class SmallRootHeapComparator implements Comparator<Integer> {
        public int compare(Integer o1, Integer o2) {
            return o1 - o2;
        }
    }
    class BigRootHeapComparator implements Comparator<Integer> {

        public int compare(Integer o1, Integer o2) {
            return o2 - o1;
        }
    }
}

统计素数个数

public static int erar(int n){
        boolean isPrime[]=new boolean[n];//false代表素数
        int count=0;
        for(int i=2;i<n;i++){
            if(!isPrime[i]){//素数
                count++;
                for(int j=2*i;j<n;j+=i){
                    isPrime[j]=true;
                }
            }
        }
        return count;
    }

三个数最大乘积

class Solution {
    public int maximumProduct(int[] nums) {
        //三个最大乘积或者最大正数*最小两个负数
        Arrays.sort(nums);
        int n = nums.length;
        return Math.max(nums[0] * nums[1] * nums[n - 1], nums[n - 3] * nums[n - 2] * nums[n - 1]);
    }
}
class Solution {
    public int maximumProduct(int[] nums) {
        //三个最大乘积或者最大正数*最小两个负数
        int max1=-65536;int max2=-65536;int max3=-65536;
        int min1=65535;int min2=65535;
        for(int i=0;i<nums.length;i++){
            if(nums[i]<min1){
                min2=min1;
                min1=nums[i];
            }else if(nums[i]<min2){
                min2=nums[i];
            }

            if(nums[i]>max1){
                max3=max2;
                max2=max1;
                max1=nums[i];
            }else if(nums[i]>max2){
                max3=max2;
                max2=nums[i];
            }else if(nums[i]>max3){
                max3=nums[i];
            }
        }
        return Math.max(max1*max2*max3,min1*min2*max1);
    }
}

排序数组的两个数之和

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        //二分查找
        iint l = 0, r = numbers.size() - 1;
        while(l<r){
            if(numbers[l] + numbers[r] == target) return new int[2]{l, r};
            else if(numbers[l] + numbers[r] > target) r--;
            else l++;
        }
        return new int[2]{l, r};
    }
}

 向数组中追加K个整数 

给你一个整数数组 nums 和一个整数 k 。请你向 nums 中追加 k 个 未 出现在 nums 中的、互不相同 的 正 整数,并使结果数组的元素和 最小 。

class Solution {
    public long minimalKSum(int[] nums, int k) {
         //数组排序,声明返回值`ans`
        Arrays.sort(nums);
        long ans = 0;
        int l = 0, r = 1;
        //若开头是1
        if (nums[0] == 1) {
            //如此往复,遍历数组内的相邻两个数字,并且加到`ans`上
            while (k > 0 && r < nums.length) {
                //没有插入的间隙
                if (nums[l] == nums[r] || nums[l] + 1 == nums[r]) {
                    l++;
                    r++;
                    continue;
                }
                if (nums[r] - nums[l]- 1 <= k) {//l,r之间的间隙不够数
                    ans += getSum(nums[l], nums[r]);
                    k -= nums[r] - nums[l] - 1;
                } else {//l,r之间的间隙够数
                    ans += getSum(nums[l], nums[l] + k + 1);
                    k = 0;
                }
                l++;
                r++;
            }
            //若数组遍历结束后,k仍然不为0,则从最大值 + 1开始,加上后面的数字,直到k为0
            int more = nums[nums.length - 1] + 1;
            while (k > 0) {
                ans += more;
                more++;
                k--;
            }
            return ans;
        }

        //若开头不是1,则先计算从1到nums[0]的数字的和并减去这些数字的数量  
        if (nums[0] - 1 >= k) {
            ans += getSum(0, 1 + k);
            return ans;
        } else {
            ans += getSum(0, nums[0]);
            k -= nums[0] - 1;
        }
         //如此往复,遍历数组内的相邻两个数字,并且加到`ans`上
        while (k > 0 && r < nums.length) {
            if (nums[l] == nums[r] || nums[l] + 1 == nums[r]) {
                l++;
                r++;
                continue;
            }
            if (nums[r] - nums[l]- 1 <= k) {
                ans += getSum(nums[l], nums[r]);
                k -= nums[r] - nums[l] - 1;
            } else {
                ans += getSum(nums[l], nums[l] + k + 1);
                k = 0;
            }
            l++;
            r++;
        }
         //若数组遍历结束后,k仍然不为0,则从最大值 + 1开始,加上后面的数字,直到k为0
        int more = nums[nums.length - 1] + 1;
        while (k > 0) {
            ans += more;
            more++;
            k--;
        }
        return ans;
    }
    //计算nums[i]与nums[i + 1]之间的和
    //1,2,3,4,5,6,7,8
    long getSum(int l, int r) {
        int quan = r - l - 1;
        long sum = 0;
        sum += (long) (l + r) * quan / 2;
        return sum;
    }
}

旋转数组 

轮转数组 

给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

class Solution {
    public void rotate(int[] nums, int k) {
        // 反转整个字符串
        // 反转区间为前k的子串
        // 反转区间为k到末尾的子串
        //如果k大于nums.size了应该怎么办,所以其实就是右移 k % nums.size() 
        int n = nums.length;
        k %= n;
        reverse(nums, 0, n - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, n - 1);
    }
    private void reverse(int[] nums, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            int temp = nums[j];
            nums[j] = nums[i];
            nums[i] = temp;
        }
    }
}

找旋转数组的最小值

class Solution {
    public int findMin(int[] nums) {
        /**
        和 I 的做法类似, 都是二分法, 每次进入无序的那部分找出最小值
        但是由于有重复值的情况, 需要加入 mid 元素等于 hi 元素的情况
        此时应该将 hi 减 1 防止重复数字是最小元素
        **/
        int lo = 0, hi = nums.length-1;
        while(lo < hi) {
            int mid = lo+(hi-lo)/2;
            if(nums[mid] > nums[hi])
                lo = mid+1;
            else if(nums[mid] < nums[hi])
                hi = mid;
            else
                hi--;
        }
        return nums[lo];
    }
}

快慢指针

删除有序数组中重复项

class Solution {
    public int removeDuplicates(int[] nums) {
        int slow=0;
        for(int i=1;i<nums.length;i++){
            if(nums[i]!=nums[slow]){
                slow++;
                nums[slow]=nums[i];
            }
        }
        return slow+1;
    }
}

移动零

class Solution {
    public void moveZeroes(int[] nums) {
        int left=0;int i=0;
        for(i=0;i<nums.length;i++){
            if(nums[i]!=0){
                nums[left++]=nums[i];
            }
        }
        for(i=left;i<nums.length;i++)nums[i]=0;
    }
}

比较含退格的字符串

class Solution {
    public boolean backspaceCompare(String s, String t) {
        String s1=doublePointer(s);
        String t1=doublePointer(t);
        return s1.equals(t1);
    }
    public String doublePointer(String s){
        int slow=0;int fast=0;
        char ss[]=s.toCharArray();
        for(;fast<ss.length;fast++){
            if(ss[fast]!='#'){
                ss[slow++]=ss[fast];
            }
            else if(ss[fast]=='#'&&slow>0){
                slow--;
            }
        }
        return String.valueOf(ss, 0, slow);
    }
}



有序数组的平方 

class Solution {
    public int[] sortedSquares(int[] nums) {
        int right = nums.length - 1;
        int left = 0;
        int[] result = new int[nums.length];
        int index = result.length - 1;
        while (left <= right) {
            if (nums[left] * nums[left] > nums[right] * nums[right]) {
                result[index--] = nums[left] * nums[left];
                ++left;
            } else {
                result[index--] = nums[right] * nums[right];
                --right;
            }
        }
        return result;
    }
}

把数组所有B放左边,G放右边

一个left指针,一个right指针

right指针发现B,与left指针交换,left++

寻找中心数组的中心下标

数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和

思路:

  1. 遍历一遍求出总和sum
  2. 遍历第二遍求中心索引左半和leftSum
    • 同时根据sum和leftSum 计算中心索引右半和rightSum
    • 判断leftSum和rightSum是否相同
class Solution {
    public int pivotIndex(int[] nums) {
        int sum=0;
        for(int num:nums){
            sum+=num;
        }
        int sum2=0;
        for(int i=0;i<nums.length;i++){
            if(sum-sum2-nums[i]==sum2){
                return i;
            }
            sum2+=nums[i];
        }
        return -1;
    }
}

螺旋旋转数组

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        int m=matrix.length;int n=matrix[0].length;
        int i=0;int j=0;int sum=0;
        int loop=Math.min(m,n)/2;
        List<Integer> list=new ArrayList();
        int startX=0;int startY=0;int offset=1;
        while(loop-->0){
            for(j=startY;j<startY+n-offset;j++){
                list.add(matrix[startX][j]);
            }
            for(i=startX;i<startX+m-offset;i++){
                list.add(matrix[i][j]);
            }
            for(;j>startY;j--){
                list.add(matrix[i][j]);
            }
            for(;i>startX;i--){
                list.add(matrix[i][j]);
            }
            startX++;
            startY++;
            offset+=2;
        }
        if (n == m &&n % 2 ==1){
            list.add(matrix[n/2][n/2]);
        }
        if(m<n&&m%2==1){
            for(i=m/2;i<n-m/2;i++){
                list.add(matrix[m/2][i]);
            }
        }
        if(m>n&&n%2==1){
            for(i=n/2;i<m-n/2;i++){
                list.add(matrix[i][n/2]);
            }
        }
        return list;
    }
}
C语言数组题目及答案 题目:求一个整型数组中的最大值和最小值,并计算平均值。 解答:可以通过遍历整型数组来求解最大值、最小值和平均值。 首先,定义一个整型数组,并赋值。假设数组名为arr,长度为n。 然后,初始化最大值和最小值为数组中的第一个元素arr[0],并初始化累加和sum为0。 接下来,使用for循环从数组的第二个元素(arr[1])开始遍历数组: - 如果当前元素arr[i]大于最大值max,则更新最大值为arr[i]; - 如果当前元素arr[i]小于最小值min,则更新最小值为arr[i]; - 将当前元素arr[i]累加到sum中。 循环结束后,最大值、最小值和sum的值就得到了。 最后,通过除以n求得数组的平均值avg,即avg = sum / n。 代码示例: #include <stdio.h> int main() { int arr[] = {5, 2, 8, 1, 9}; // 定义整型数组并赋值 int n = sizeof(arr) / sizeof(arr[0]); // 数组长度 int max = arr[0]; // 初始化最大值 int min = arr[0]; // 初始化最小值 int sum = 0; // 初始化累加和 float avg = 0; // 初始化平均值 for (int i = 1; i < n; i++) { if (arr[i] > max) { max = arr[i]; // 更新最大值 } if (arr[i] < min) { min = arr[i]; // 更新最小值 } sum += arr[i]; // 累加 } avg = (float)sum / n; // 计算平均值 printf("最大值:%d\n", max); printf("最小值:%d\n", min); printf("平均值:%f\n", avg); return 0; } 运行以上代码,输出结果为: 最大值:9 最小值:1 平均值:5.000000 这样,我们就可以通过遍历数组来求解最大值、最小值和平均值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值