0
点赞
收藏
分享

微信扫一扫

JAVA练习168-绘制直线

棒锤_45f2 2022-02-25 阅读 81

绘制直线。有个单色屏幕存储在一个一维数组中,使得32个连续像素可以存放在一个 int 里。屏幕宽度为w,且w可被32整除(即一个 int 不会分布在两行上),屏幕高度可由数组长度及屏幕宽度推算得出。请实现一个函数,绘制从点(x1, y)到点(x2, y)的水平线。

给出数组的长度 length,宽度 w(以比特为单位)、直线开始位置 x1(比特为单位)、直线结束位置 x2(比特为单位)、直线所在行数 y。返回绘制过后的数组。

示例1:
 输入:length = 1, w = 32, x1 = 30, x2 = 31, y = 0
 输出:[3]
 说明:在第0行的第30位到第31为画一条直线,屏幕表示为[0b000000000000000000000000000000011]

示例2:
 输入:length = 3, w = 96, x1 = 0, x2 = 95, y = 0
 输出:[-1, -1, -1]

分析:

方法:模拟

可以通过 w * y + x1 的方式,将二维平面转化为一维,那么对目标范围的直线的情况进行讨论即可:

图1
图2
  1. 目标直线不在当前范围内,如 [ 0,32 ) 和 [ 128,160 ),此时全 0。
  2. 左边界在当前范围内,如图1 [ 32,64 ),此时 left 左边全 0,右边全 1。
  3. 当前范围在目标直线内,如图1 [ 64,96 ),此时全 1。
  4. 右边界在当前范围内,如图1 [ 96,128 ),此时 right 左边全 1,右边全 0。
  5. 目标直线都在当前范围内,如图2 [ 65,96 ),此时 [ left,right ] 全 1,其余全 0。

时间复杂度:O(n)        n 为 length
空间复杂度:O(n) 

    public int[] drawLine(int length, int w, int x1, int x2, int y) {
        //结果数组
        int[] res = new int[length];
        //定义左右边界
        int left = w * y + x1, right = w * y + x2;
        //遍历,记录每32位的数字
        for(int i = 0; i <length; ++i){
            //当前范围左右边界
            int cur = i * 32, next = cur + 31;
            //目标范围都不在范围里
            //当前范围在目标范围外
            if(next < left || cur > right){
                continue;
            }
            //当范围在目标范围内
            if(cur >= left && next <= right){
                res[i] = -1;
                continue;
            }
            //目标范围仅在当前范围里
            if(cur <= left && right <= next){
                res[i] = -1 >>> left % 32 & -1 << 31 - right % 32;
                continue;
            }
            //左边界部分在当前范围内
            if(cur <= left){
                res[i] = -1 >>> left % 32;
                continue;
            }
            //右边界部分在当前范围内
            res[i] = -1 << 31 - right % 32;
        }
        return res;
    }

优化:

因为Java 整形数组默认为 0,索引只需要将直线中间的范围赋为 -1,然后单独计算左右边界即可。

时间复杂度:O(n)        最坏情况,全是1
空间复杂度:O(n) 

class Solution {
    public int[] drawLine(int length, int w, int x1, int x2, int y) {
        //结果数组
        int[] res = new int[length];
        //定义左右边界
        int left = (w * y + x1) / 32, right = (w * y + x2) / 32;
        //对中间进行赋值
        for(int i = left + 1; i <= right; ++i){
            res[i] = -1;
        }
        //左边界
        res[left] = -1 >>> x1 % 32;
        //右边界
        res[right] = res[right] & Integer.MIN_VALUE >> x2 % 32;
        return res;
    }
}

题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/draw-line-lcci

举报

相关推荐

0 条评论