算法数据结构系列-实践篇-数组算法

@TOC

Offer-03 数组中重复的数字

问题描述:在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

public int findRepeatNumber(int[] nums) {
    if (nums == null || nums.length < 1) {
        return -1;
    }
    int len = nums.length;
    for (int i = 0; i < len; i++) {
        int index = nums[i] % len;// 通过取余,获取数字原来的数,但仅作为索引使用,并改变当前遍历点i的值
        if (nums[index] >= len) {//是index不是i,要判断index是否重复
            return nums[i] % len;
        }
        nums[index] += len;//加length方便,将数还原
    }
    return -1;
}

Offer-66 构建乘积数组

问题描述:给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1],不能使用除法,具体可参考Offer-66题
![在这里插入图片描述](https://upload-images.jianshu.io/upload_images/10870216-76326b026893fb1e.png =500x)

public int[] constructArr(int[] a) {
    int[] b = new int[a.length];
    b[0] = 1;
    for (int i = 1; i < a.length; i++) {
        b[i] = b[i - 1] * a[i - 1];
    }
    int tmp = 1;
    for (int i = a.length - 2; i >= 0; i--) {
        tmp = tmp * a[i+1];
        b[i] = tmp * b[i];
    }
    return b;
}

Offer-45 把数组排成最小的数

问题描述 :输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。如果输入: [10,2],输出: "102",具体可参考Offer-45题。关于排序的规则理解,可以亲自按插入排序试一下。

在这里插入图片描述

public String minNumber(Integer[] nums) {
    if (nums == null || nums.length < 1) {
        return "";
    }

    Arrays.sort(nums, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            String x = o1.toString() + o2.toString();
            String y = o2.toString() + o1.toString();
            return x.compareTo(y);
        }
    });

    StringBuilder sb = new StringBuilder();
    for (Integer num : nums) {
        sb.append(num);
    }
    return sb.toString();
}

Offer-49 判断丑数

问题描述:我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number),求按从小到大的顺序的第 n 个丑数。蛮力法:根据丑数定义,若一个数能被2整除,则连续除以2;若还能被3整除,则连续除以3;若还能被5整除,则连续除以5;如果最后结果是1则是丑数,否则不是;动态规划:新丑数,是前面已经生成的丑数的2倍或3倍或5倍。具体详见Offer-49题

在这里插入图片描述

在这里插入图片描述

Offer-29 顺时针打印矩阵

问题描述:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。输入:matrix = [[1,2,3],[4,5,6],[7,8,9]],输出:[1,2,3,6,9,8,7,4,5]。

在这里插入图片描述

public int[] spiralOrder2(int[][] matrix) {
    if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
        return new int[0];
    }

    int cols = matrix[0].length;
    int rows = matrix.length;
    int[] order = new int[cols * rows];
    int top = 0, bottom = rows - 1, left = 0, right = cols - 1;
    int index = 0;
    while (index < order.length) {
        for (int column = left; column <= right; column++) {
            order[index++] = matrix[top][column];
        }
        if (index == order.length) {
            break;
        }

        for (int row = top + 1; row <= bottom; row++) {
            order[index++] = matrix[row][right];
        }
        if (index == order.length) {
            break;
        }

        for (int column = right - 1; column > left; column--) {
            order[index++] = matrix[bottom][column];
        }
        if (index == order.length) {
            break;
        }

        for (int row = bottom; row > top; row--) {
            order[index++] = matrix[row][left];
        }

        top++; bottom--; left++; right--;
    }
    return order;
}

offer-61 扑克牌中的顺子

从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。输入: [1,2,3,4,5],输出: True;输入: [0,0,1,2,5],输出: True;

在这里插入图片描述

public boolean isStraight(int[] nums) {
    Set<Integer> set = new HashSet<>();
    int min = 15, max = -1;
    for (int num : nums) {
        if (set.contains(num)) {
            return false;
        }
        if (num == 0) {
            continue;
        }

        set.add(num);
        min = Math.min(min, num);
        max = Math.max(max, num);
    }
    return (max - min) < 5;
}

Offer-57 和为s的两个数字

问题描述:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

在这里插入图片描述

public int[] twoSum(int[] nums, int target) {
    if (nums == null || nums.length < 3) {
        return nums;
    }

    int i = 0, j = nums.length - 1;
    while (i < j) {
        int s = nums[i] + nums[j];
        if (s == target) {
            return new int[]{nums[i], nums[j]};
        }
        if (s < target) {
            i++;
            continue;
        }
        j--;
    }
    return new int[0];
}

Offer-57-II 和为s的连续正数序列

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。输入:target = 9,输出:[[2,3,4],[4,5]]

在这里插入图片描述

public int[][] findContinuousSequence(int target) {
    int i = 1; // 滑动窗口的左边界
    int j = 1; // 滑动窗口的右边界
    int sum = 0; // 滑动窗口中数字的和
    List<int[]> list = new ArrayList<>();
    while (i <= target / 2) {
        if (sum < target) {
            sum += j;
            j++;
            continue;
        }

        if (sum > target) {
            sum -=i;
            i++;
            continue;
        }

        int[] arr = new int[j-i]; // 记录结果
        for (int k = i; k < j; k++) {
            arr[k-i] = k;
        }
        list.add(arr);
        sum -= i;// 左边界向右移动
        i++;
    }
    return list.toArray(new int[list.size()][]);
}

Offer-59-1 滑动窗口的最大值

问题描述:给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

在这里插入图片描述

public Integer[] maxSlidingWindow(Integer[] nums, int k) {
    if (nums == null || nums.length < 1) {
        return new Integer[0];
    }
    Integer[] result = new Integer[nums.length - k + 1];
    Deque<Integer> queue = new LinkedList<>();
    for (int i = 0; i < k; i++) {
        while (!queue.isEmpty() && queue.peekLast() < nums[i]) { // 查找插入位置
            queue.removeLast();
        }
        queue.offer(nums[i]);
    }
    Integer index = 0;
    result[index++] = queue.peekFirst();
    for (int j = k; j < nums.length; j++) {
        if (nums[j - k] == queue.peekFirst()) {
            queue.removeFirst();
        }
        while (!queue.isEmpty() && queue.peekLast() < nums[j]) { // 查找插入位置
            queue.removeLast();
        }
        queue.offer(nums[j]);
        result[index++] = queue.peekFirst();
    }
    return result;
}

Offer-44 数字序列中某一位的数字

数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。请写一个函数,求任意第n位对应的数字。

在这里插入图片描述

public int findNthDigit(int n) {
    int digit = 1;
    long start = 1, count = 9;
    while (n > count) { // 求所在的数字的位数
        n -= count;
        digit++;
        start *= 10;
        count = 9 * start * digit;
    }
    long num = start + (n-1)/digit; // 求坐在数字
    return Long.toString(num).charAt(((n - 1) % digit)) -'0';
}

Offer-39 数组中出现次数超过一半的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。你可以假设数组是非空的,并且给定的数组总是存在多数元素。

在这里插入图片描述

public int majorityElement(int[] nums) {
    if (nums == null || nums.length < 1) {
        return -1;
    }

    int vote = 0, x = -1;
    for (int num : nums) {
        if (vote == 0) {
            x = num;
        }
        vote += num == x ? 1 : -1;
    }
    return x;
}

面试题-01-08 零矩阵

问题描述:编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零,具体详见 金典01-08题
![在这里插入图片描述](https://upload-images.jianshu.io/upload_images/10870216-41b01c0926d77009.png =350x)

public void setZeroes(int[][] matrix) {
    if (matrix == null || matrix.length < 1) {
        return;
    }
    boolean[] rows = new boolean[matrix.length];
    boolean[] cols = new boolean[matrix[0].length];

    for (int i = 0; i < rows.length; i++) {
        for (int j = 0; j < cols.length; j++) {
            if (matrix[i][j] == 0) {
                rows[i] = true;
                cols[j] = true;
            }
        }
    }

    for (int i = 0; i < rows.length; i++) {
        for (int j = 0; j < cols.length; j++) {
            if (rows[i] || cols[j]) {
                matrix[i][j] = 0;
            }
        }
    }
}

面试题-01-07 旋转矩阵

问题描述:给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。不占用额外内存空间能否做到。
![在这里插入图片描述](https://upload-images.jianshu.io/upload_images/10870216-5c9ced8961680c5f.png =600x)

在这里插入图片描述

本文由mdnice多平台发布

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,527评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,314评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,535评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,006评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,961评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,220评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,664评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,351评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,481评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,397评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,443评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,123评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,713评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,801评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,010评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,494评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,075评论 2 341

推荐阅读更多精彩内容