[左神面试指南] 数组和矩阵[上]篇

发布时间 2023-11-22 18:48:29作者: Vivid-BinGo

CD149 转圈打印矩阵

public class CD149_1
{
    public static void solution(int[][] arr)
    {
        int up = 0, down = arr.length - 1, left = 0, right = arr[0].length - 1;
        while (up <= down && left <= right)
        {
            for (int i = left; i <= right; i++)
                System.out.print(arr[up][i] + " ");
            for (int i = up + 1; i < down; i++)
                System.out.print(arr[i][right] + " ");
            for (int i = right; up != down && i >= left; i--)
                System.out.print(arr[down][i] + " ");
            for (int i = down - 1; left != right && i > up; i--)
                System.out.print(arr[i][left] + " ");
            up++;
            down--;
            left++;
            right--;
        }
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int m, n;
        m = in.nextInt();
        n = in.nextInt();
        int[][] arr = new int[m][n];
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                arr[i][j] = in.nextInt();
        solution(arr);
    }
}

CD150 将正方形矩阵顺时针转动 90°

public class CD150_1
{
    public static void solution(int[][] arr)
    {
        int n = arr.length;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (i < j) break;
                int temp = arr[i][j];
                arr[i][j] = arr[j][i];
                arr[j][i] = temp;
            }
        }
        for (int i = 0; i < n; i++)
        {
            int l = 0, r = n - 1;
            while (l <= r)
            {
                int temp = arr[i][l];
                arr[i][l] = arr[i][r];
                arr[i][r] = temp;
                l++;
                r--;
            }
        }
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
                System.out.print(arr[i][j] + (j == n - 1 ? "" : " "));
            System.out.println();
        }
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        n = in.nextInt();
        int[][] arr = new int[n][n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                arr[i][j] = in.nextInt();
        solution(arr);
    }
}

CD151 “之”字形打印矩阵

public class CD151_1
{
    public static void solution(int[][] arr)
    {
        int x = 0, y = 0, m = arr.length - 1, n = arr[0].length - 1;
        boolean up = true;
        while (x != m || y != n)
        {
            if (up)
            {
                while (x >= 0 && y <= n)
                    System.out.print(arr[x--][y++] + " ");
                if (y == n + 1)
                {
                    x += 2;
                    y = n;
                }
                else if (x == -1) x = 0;
            }
            else
            {
                while (x <= m && y >= 0)
                    System.out.print(arr[x++][y--] + " ");
                if (x == m + 1)
                {
                    x = m;
                    y += 2;
                }
                else if (y == -1)
                    y = 0;
            }
            up = !up;
        }
        System.out.println(arr[m][n]);
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int m, n;
        m = in.nextInt();
        n = in.nextInt();
        int[][] arr = new int[m][n];
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                arr[i][j] = in.nextInt();
        solution(arr);
    }
}

CD152 找到无序数组中最小的 k 个数 ⭐

/* 堆 */
public class CD152_1
{
    public static void solution(int[] arr, int k)
    {
        int len = arr.length - 1;
        for (int i = (len - 1) / 2; i >= 0; i--)
            adjustHeap(arr, i, len);
        while (k-- > 0)
        {
            System.out.print(arr[0] + " ");
            arr[0] = arr[len--];
            adjustHeap(arr, 0, len);
        }
    }

    public static void adjustHeap(int[] arr, int idx, int len)
    {
        int cur;
        while (2 * idx + 1 <= len)
        {
            cur = 2 * idx + 1;
            if (2 * idx + 2 <= len && arr[2 * idx + 1] > arr[2 * idx + 2])
                cur++;
            if (arr[idx] > arr[cur])
            {
                int temp = arr[idx];
                arr[idx] = arr[cur];
                arr[cur] = temp;
            }
            else break;
            idx = cur;
        }
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, k;
        n = in.nextInt();
        k = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        solution(arr, k);
    }
}

/* ⭐BFPRT算法⭐ */
public class CD152_2
{
    public static int[] solution(int[] arr, int k)
    {
        if (k < 1 || k > arr.length) return arr;
        int minKth = getMinKthByBFPRT(arr, k);
        int[] res = new int[k];
        int index = 0;
        for (int i = 0; i != arr.length; i++)
            if (arr[i] < minKth)
                res[index++] = arr[i];
        for (; index != res.length; index++)
            res[index] = minKth;
        return res;
    }

    public static int getMinKthByBFPRT(int[] arr, int K)
    {
        int[] copyArr = new int[arr.length];
        System.arraycopy(arr, 0, copyArr, 0, arr.length);
        return select(copyArr, 0, copyArr.length - 1, K - 1);
    }


    public static int select(int[] arr, int begin, int end, int i)
    {
        if (begin == end) return arr[begin];
        int pivot = medianOfMedians(arr, begin, end);
        int[] pivotRange = partition(arr, begin, end, pivot);
        if (i >= pivotRange[0] && i <= pivotRange[1])
            return arr[i];
        else if (i < pivotRange[0])
            return select(arr, begin, pivotRange[0] - 1, i);
        else
            return select(arr, pivotRange[1] + 1, end, i);
    }

    public static int medianOfMedians(int[] arr, int begin, int end)
    {
        int num = end - begin + 1;
        int offset = num % 5 == 0 ? 0 : 1;
        int[] mArr = new int[num / 5 + offset];
        for (int i = 0; i < mArr.length; i++)
        {
            int beginI = begin + i * 5;
            int endI = beginI + 4;
            mArr[i] = getMedian(arr, beginI, Math.min(end, endI));
        }
        return select(mArr, 0, mArr.length - 1, mArr.length / 2);
    }

    public static int[] partition(int[] arr, int begin, int end, int pivotValue)
    {
        int small = begin - 1;
        int cur = begin;
        int big = end + 1;
        while (cur != big)
        {
            if (arr[cur] < pivotValue)
                swap(arr, ++small, cur++);
            else if (arr[cur] > pivotValue)
                swap(arr, cur, --big);
            else
                cur++;
        }
        int[] range = new int[2];
        range[0] = small + 1;
        range[1] = big - 1;
        return range;
    }

    public static int getMedian(int[] arr, int begin, int end)
    {
        insertionSort(arr, begin, end);
        int sum = end + begin;
        int mid = (sum / 2) + (sum % 2);
        return arr[mid];
    }

    public static void insertionSort(int[] arr, int begin, int end)
    {
        for (int i = begin + 1; i != end + 1; i++)
        {
            for (int j = i; j != begin; j--)
            {
                if (arr[j - 1] > arr[j])
                    swap(arr, j - 1, j);
                else
                    break;
            }
        }
    }

    public static void swap(int[] arr, int i, int j)
    {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }


    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, k;
        n = in.nextInt();
        k = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        int[] res = solution(arr, k);
        System.out.println(Arrays.stream(res).mapToObj(String::valueOf).collect(Collectors.joining(" ")));
    }
}

CD153 需要排序的最短子数组长度⭐

/*⭐⭐*/
public class CD153_1
{
    public static int solution(int[] arr)
    {
        int maxIdx = -1, minIdx = -1, mmax, mmin;
        mmax = arr[0];
        for (int i = 1; i < arr.length; i++)
        {
            if (arr[i] < mmax)
                maxIdx = i;
            else
                mmax = arr[i];
        }
        if (maxIdx == -1) return 0;
        mmin = arr[arr.length - 1];
        for (int i = arr.length - 2; i >= 0; i--)
        {
            if (arr[i] > mmin)
                minIdx = i;
            else
                mmin = arr[i];
        }
        return maxIdx - minIdx + 1;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr));
    }
}

CD154 在数组中找到出现次数大于一半的数

/* 摩尔投票 */
public class CD154_1
{
    public static int solution(int[] arr)
    {
        int cnt = 0, ans = -1;
        for (int num : arr)
        {
            if (cnt == 0 || ans == num)
            {
                ans = num;
                cnt++;
            }
            else
                cnt--;
        }
        cnt = 0;
        for (int num : arr)
            if (num == ans)
                cnt++;
        if (cnt > arr.length / 2) return ans;
        else return -1;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr));
    }
}

CD155 在数组中找到出现次数大于 N/K 的数⭐

/* ⭐摩尔投票⭐ */
public class CD155_1
{
    public static void solution(int[] arr, int k)
    {
        HashMap<Integer, Integer> cands = new HashMap<>();
        HashMap<Integer, Integer> cnt = new HashMap<>();
        boolean flag;
        for (int num : arr)
        {
            if (cands.containsKey(num))
                cands.put(num, cands.get(num) + 1);
            else
            {
                if (cands.size() < k - 1)
                    cands.put(num, 1);
                else
                {
                    ArrayList<Integer> removeList = new ArrayList<>();
                    Set<Integer> keySet = cands.keySet();
                    for (int key : keySet)
                    {
                        if (cands.get(key) == 1)
                            removeList.add(key);
                        else cands.put(key, cands.get(key) - 1);
                    }
                    for (int key : removeList)
                        cands.remove(key);
                    if (removeList.size() != 0)
                        cands.put(num, 1);
                }
            }
        }
        for (int num : arr)
            if (cands.containsKey(num))
                cnt.put(num, cnt.getOrDefault(num, 0) + 1);
        Set<Integer> keySet = cnt.keySet();
        flag = false;
        for (int key : keySet)
        {
            if (cnt.get(key) > arr.length / k)
            {
                flag = true;
                System.out.print(key + " ");
            }
        }
        if (!flag)
            System.out.println("-1");
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, k;
        n = in.nextInt();
        k = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        solution(arr, k);
    }
}

CD1 在行列都排好序的矩阵中找指定数

public class CD1_1
{
    public static boolean solution(int[][] arr, int k)
    {
        int row = 0, col = arr[0].length - 1;
        while (col >= 0 && row <= arr.length - 1)
        {
            if (arr[row][col] == k) return true;
            else if (arr[row][col] > k) col--;
            else row++;
        }
        return false;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, m, k;
        n = in.nextInt();
        m = in.nextInt();
        k = in.nextInt();
        int[][] arr = new int[n][m];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                arr[i][j] = in.nextInt();
        System.out.println(solution(arr, k) ? "Yes" : "No");
    }
}

CD2 最长的可整合子数组的长度

public class CD2_1
{
    public static int solution(int[] arr)
    {
        HashSet<Integer> set = new HashSet<>();
        int mmax, mmin, ans = 1;
        for (int i = 0; i < arr.length; i++)
        {
            set.clear();
            mmax = Integer.MIN_VALUE;
            mmin = Integer.MAX_VALUE;
            for (int j = i; j < arr.length; j++)
            {
                if (set.contains(arr[j])) break;
                set.add(arr[j]);
                mmax = Math.max(mmax, arr[j]);
                mmin = Math.min(mmin, arr[j]);
                if (mmax - mmin == j - i)
                    ans = Math.max(ans, j - i + 1);
            }
        }
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr));
    }
}

CD3 不重复打印排序数组中相加和为给定值的所有二元组

/* 双指针 */
public class CD3_1
{
    public static void solution(int[] arr, int k)
    {
        int l = 0, r = arr.length - 1;
        while (l < r)
        {
            if (arr[l] + arr[r] == k)
            {
                if (l == 0 || arr[l] != arr[l - 1])
                    System.out.println(arr[l] + " " + arr[r]);
                l++;
            }
            else if (arr[l] + arr[r] < k) l++;
            else r--;
        }
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, k;
        n = in.nextInt();
        k = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        solution(arr, k);
    }
}

CD4 不重复打印排序数组中相加和为给定值的所有三元组

/* 双指针 */
public class CD4_1
{
    public static void solution(int[] arr, int k)
    {
        for (int i = 0; i < arr.length; i++)
            if (i == 0 || arr[i] != arr[i - 1])
                cal(arr, k - arr[i], i, i + 1);
    }

    public static void cal(int[] arr, int k, int f, int s)
    {
        if (s >= arr.length) return;
        int l = s, r = arr.length - 1;
        while (l < r)
        {
            if (arr[l] + arr[r] == k)
            {
                if ((l == 0 || arr[l] != arr[l - 1]) && arr[l] < arr[r])
                    System.out.println(arr[f] + " " + arr[l] + " " + arr[r]);
                l++;
            }
            else if (arr[l] + arr[r] < k) l++;
            else r--;
        }
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, k;
        n = in.nextInt();
        k = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        solution(arr, k);
    }
}

CD8 未排序正数数组中累加和为给定值的最长子数组长度

/* 滑动窗口 */
public class CD8_1
{
    public static int solution(int[] arr, int k)
    {
        int l = 0, r = 0, sum = 0, ans = -1;
        while (r < arr.length)
        {
            while (r < arr.length && sum < k)
                sum += arr[r++];
            if (sum == k)
                ans = Math.max(ans, r - l);
            sum -= arr[l];
            l++;
        }
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, k;
        n = in.nextInt();
        k = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr, k));
    }
}

CD9 未排序数组中累加和为给定值的最长子数组长度⭐

/*⭐⭐*/
public class CD9_1
{
    public static int solution(int[] arr, int k)
    {
        int sum = 0, ans = -1;
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(0, -1);
        for (int i = 0; i < arr.length; i++)
        {
            sum += arr[i];
            if (map.containsKey(sum - k))
                ans = Math.max(ans, i - map.get(sum - k));
            if (!map.containsKey(sum))
                map.put(sum, i);
        }
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, k;
        n = in.nextInt();
        k = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr, k));
    }
}

CD10 未排序数组中累加和为给定值的最长子数组长度(补充1)

public class CD10_1
{
    public static int solution(int[] arr)
    {
        for (int i = 0; i < arr.length; i++)
        {
            if (arr[i] > 0) arr[i] = 1;
            else if (arr[i] < 0) arr[i] = -1;
        }
        int sum = 0, ans = -1;
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(0, -1);
        for (int i = 0; i < arr.length; i++)
        {
            sum += arr[i];
            if (map.containsKey(sum))
                ans = Math.max(ans, i - map.get(sum));
            else
                map.put(sum, i);
        }
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr));
    }
}

CD11 未排序数组中累加和为给定值的最长子数组长度(补充2)

public class CD11_1
{
    public static int solution(int[] arr)
    {
        for (int i = 0; i < arr.length; i++)
            if (arr[i] == 0) arr[i] = -1;
        int sum = 0, ans = -1;
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(0, -1);
        for (int i = 0; i < arr.length; i++)
        {
            sum += arr[i];
            if (map.containsKey(sum))
                ans = Math.max(ans, i - map.get(sum));
            else
                map.put(sum, i);
        }
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr));
    }
}

CD14 未排序数组中累加和小于或等于给定值的最长子数组长度⭐

/*⭐二分⭐*/
public class CD14_1
{

    public static int solution(int[] arr, int k)
    {
        int sum, ans = -1;
        int[] h = new int[arr.length];
        sum = h[0] = arr[0];
        for (int i = 1; i < arr.length; i++)
        {
            sum += arr[i];
            h[i] = Math.max(h[i - 1], sum);
        }
        sum = 0;
        for (int i = 0; i < arr.length; i++)
        {
            sum += arr[i];
            int f = binSearch(h, sum - k);
            int len = sum <= k ? i + 1 : i - f;
            ans = Math.max(ans, len);
        }
        return ans;
    }

    public static int binSearch(int[] h, int num)
    {
        int l = 0, r = h.length - 1, mid;
        while (l <= r)
        {
            mid = (l + r) / 2;
            if (h[mid] < num)
                l = mid + 1;
            else r = mid - 1;
        }
        return l;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, k;
        n = in.nextInt();
        k = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr, k));
    }
}

/*⭐滑动窗口⭐*/
public class CD14_2
{

    public static int solution(int[] arr, int k)
    {
        int len = arr.length, l = 0, r = 0, sum = 0, ans = -1;
        int[] minVal = new int[len];
        int[] minEnd = new int[len];
        minVal[len - 1] = arr[len - 1];
        minEnd[len - 1] = len - 1;
        for (int i = len - 2; i >= 0; i--)
        {
            if (minVal[i + 1] < 0)
            {
                minVal[i] = arr[i] + minVal[i + 1];
                minEnd[i] = minEnd[i + 1];
            }
            else
            {
                minVal[i] = arr[i];
                minEnd[i] = i;
            }
        }
        for (l = 0; l < len; l++)
        {
            sum = 0;
            r = l;
            while (r < arr.length && sum + minVal[r] <= k)
            {
                sum += minVal[r];
                r = minEnd[r] + 1;
            }
            ans = Math.max(ans, r - l);
        }
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, k;
        n = in.nextInt();
        k = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr, k));
    }
}

CD21 计算数组的小和

/* 归并 */
public class CD21_1
{

    public static long solution(int[] arr)
    {
        return partition(arr, 0, arr.length - 1);
    }

    public static long partition(int[] arr, int l, int r)
    {
        if (l >= r) return 0;
        int mid = (l + r) / 2;
        long left = partition(arr, l, mid);
        long right = partition(arr, mid + 1, r);
        return left + right + merge(arr, l, mid, r);
    }

    public static long merge(int[] arr, int l, int mid, int r)
    {
        int i = l, j = mid + 1, idx = 0;
        long ans = 0;
        int[] temp = new int[r - l + 1];
        while (i <= mid && j <= r)
        {
            if (arr[i] <= arr[j])
            {
                ans += arr[i] * (r - j + 1);
                temp[idx++] = arr[i++];
            }
            else
                temp[idx++] = arr[j++];
        }
        while (i <= mid)
            temp[idx++] = arr[i++];
        while (j <= r)
            temp[idx++] = arr[j++];
        System.arraycopy(temp, 0, arr, l, r - l + 1);
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr));
    }
}

CD23 自然数数组的排序

/* 模拟 */
public class CD23_1
{
    public static int[] solution(int[] arr)
    {
        for (int i = 0; i < arr.length; i++)
        {
            if (arr[i] == i + 1) continue;
            int temp = arr[arr[i] - 1];
            arr[arr[i] - 1] = arr[i];
            arr[i] = temp;
            i--;
        }
        return arr;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        int[] res = solution(arr);
        System.out.println(Arrays.stream(res).mapToObj(String::valueOf).collect(Collectors.joining(" ")));
    }
}

CD24 奇数下标都是奇数或者偶数下标都是偶数

public class CD24_1
{
    public static int[] solution(int[] arr)
    {
        int even = 0, odd = 1, idx = arr.length - 1;
        while (even <= idx && odd <= idx)
        {
            if (arr[idx] % 2 == 0)
            {
                swap(arr, idx, even);
                even += 2;
            }
            else
            {
                swap(arr, idx, odd);
                odd += 2;
            }
        }
        return arr;
    }

    public static void swap(int[] arr, int i, int j)
    {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        int[] res = solution(arr);
        System.out.println(Arrays.stream(res).mapToObj(String::valueOf).collect(Collectors.joining(" ")));
    }
}