Quantcast
Channel: CSDN博客推荐文章
Viewing all 35570 articles
Browse latest View live

Android单元测试(三):PowerMock框架的使用

$
0
0

之前的两篇文章分别说到了 JUnitMockito ,一个主要用于断言,一个用于模拟我们的非测试类。今天说一说PowerMock ,它拓展了Mockito框架,从而支持了mock static方法、private方法、final方法与类等等。(这里八卦一下,为什么 Mockito 不自己支持 private 方法?有兴趣的自行查看原因

1.PowerMock选择

PowerMock 主要围绕着 Junit 测试框架和 TestNg 测试框架,在安卓中我们常用Junit + Mockito + PowerMock 组合。既然PowerMock是拓展Mockito,所以使用时,我们要找到与Mockito对应的PowerMock 支持版本去使用。

这里写图片描述

这里我们使用如下对应版本:

testCompile "org.mockito:mockito-core:2.8.9"

testCompile "org.powermock:powermock-module-junit4:1.7.3"
testCompile "org.powermock:powermock-module-junit4-rule:1.7.3"
testCompile "org.powermock:powermock-api-mockito2:1.7.3" //注意这里是mockito2
testCompile "org.powermock:powermock-classloading-xstream:1.7.3"

2.PowerMock使用

首先我们定义一个Fruit类,Banana继承于它。其中有我们后面需要mock的static、private等方法。

abstract class Fruit {

    private String fruit = "水果";

    public String getFruit() {
        return fruit;
    }
}
public class Banana extends Fruit{

    private static String COLOR = "黄色的";

    public Banana() {}

    public static String getColor() {
        return COLOR;
    }

    public String getBananaInfo() {
        return flavor() + getColor();
    }

    private String flavor() {
        return "甜甜的";
    }

    public final boolean isLike() {
        return true;
    }
}

1.mock静态方法

@RunWith(PowerMockRunner.class)
public class PowerMockitoStaticMethodTest {

    @Test
    @PrepareForTest({Banana.class})
    public void testStaticMethod() { 
        PowerMockito.mockStatic(Banana.class); //<-- mock静态类
        Mockito.when(Banana.getColor()).thenReturn("绿色");
        Assert.assertEquals("绿色", Banana.getColor());
    }
}

首先使用PowerMock必须加注解@PrepareForTest@RunWith(PowerMockRunner.class)。注解@PrepareForTest里写的是静态方法所在的类。

如果我们要更改类的私有static常量,比如修改Banana中的COLOR

@Test
@PrepareForTest({Banana.class})
public void testChangeColor() { 
    Whitebox.setInternalState(Banana.class, "COLOR", "红色的");
    Assert.assertEquals("红色的", Banana.getColor());
}

2.mock私有方法

@RunWith(PowerMockRunner.class)
public class PowerMockitoPrivateMethodTest {

    @Test
    @PrepareForTest({Banana.class})
    public void testPrivateMethod() throws Exception {
        Banana mBanana = PowerMockito.mock(Banana.class);
        PowerMockito.when(mBanana.getBananaInfo()).thenCallRealMethod();
        PowerMockito.when(mBanana, "flavor").thenReturn("苦苦的");
        Assert.assertEquals("苦苦的黄色的", mBanana.getBananaInfo());
        //验证flavor是否调用了一次
        PowerMockito.verifyPrivate(mBanana).invoke("flavor"); 
    }
}

我们通过mock私有方法flavor,使得之前的“甜甜的”变为了“苦苦的”。当然我们也可以跳过私有方法,代码如下:

    @Test
    @PrepareForTest({Banana.class})
    public void skipPrivateMethod() {
        Banana mBanana = new Banana();
        //跳过flavor方法
        PowerMockito.suppress(PowerMockito.method(Banana.class, "flavor")); 
        Assert.assertEquals("null黄色的", mBanana.getBananaInfo()); 
    }

因为跳过了flavor方法,最终输出结果为“null黄色的”。

如果我们要更改更改父类私有变量,比如修改Fruit中的fruit

    @Test
    @PrepareForTest({Banana.class})
    public void testChangeParentPrivate() throws Exception {
        Banana mBanana = new Banana();
        MemberModifier.field(Banana.class, "fruit").set(mBanana, "蔬菜");
        Assert.assertEquals("蔬菜", mBanana.getFruit());
    }

3.mock final方法

@RunWith(PowerMockRunner.class)
public class PowerMockitoFinalMethodTest {

    @Test
    @PrepareForTest({Banana.class})
    public void testFinalMethod() throws Exception {
        Banana mBanana = PowerMockito.mock(Banana.class);
        PowerMockito.when(mBanana.isLike()).thenReturn(false);
        Assert.assertFalse(mBanana.isLike());
    }
}

使用方法和使用mockito一样,但是我们通过PowerMock,成功修改了isLike方法的返回值。

4.mock 构造方法

    @Test
    @PrepareForTest({Banana.class})
    public void testNewClass() throws Exception {
        Banana mBanana = PowerMockito.mock(Banana.class);
        PowerMockito.when(mBanana.getBananaInfo()).thenReturn("大香蕉");
        //如果new新对象,则返回这个上面设置的这个对象
        PowerMockito.whenNew(Banana.class).withNoArguments().thenReturn(mBanana);
        //new新的对象
        Banana newBanana = new Banana();
        Assert.assertEquals("大香蕉", newBanana.getBananaInfo());
    }

whenNew 方法的意思是之后 new 这个对象时,返回某个被 Mock 的对象而不是让真的 new 新的对象。如果构造方法有参数,可以在withNoArguments方法中传入。

5.其他

上面我们有说到使用PowerMock就必须加@RunWith(PowerMockRunner.class),但是我们毕竟有时会使用多个测试框架,可能@RunWith会占用。这时我们可以使用@Rule。代码如下:

@Rule
public PowerMockRule rule = new PowerMockRule();

记住使用这种方法需要加入依赖:

testCompile "org.powermock:powermock-module-junit4-rule:1.7.3"
testCompile "org.powermock:powermock-classloading-xstream:1.7.3"

本篇所有代码已上传至Github。希望大家多多点赞支持!

3.参考

作者:qq_17766199 发表于2017/11/19 11:29:55 原文链接
阅读:0 评论:0 查看评论

Kafka Producer拦截器

$
0
0

Kafka中的拦截器(Interceptor)是0.10.x.x版本引入的一个功能,一共有两种:Kafka Producer端的拦截器和Kafka Consumer端的拦截器。本篇主要讲述的是Kafka Producer端的拦截器,它主要用来对消息进行拦截或者修改,也可以用于Producer的Callback回调之前进行相应的预处理。

使用Kafka Producer端的拦截器非常简单,主要是实现ProducerInterceptor接口,此接口包含4个方法:

  1. ProducerRecord<K, V> onSend(ProducerRecord<K, V> record):Producer在将消息序列化和分配分区之前会调用拦截器的这个方法来对消息进行相应的操作。一般来说最好不要修改消息ProducerRecord的topic、key以及partition等信息,如果要修改,也需确保对其有准确的判断,否则会与预想的效果出现偏差。比如修改key不仅会影响分区的计算,同样也会影响Broker端日志压缩(Log Compaction)的功能。
  2. void onAcknowledgement(RecordMetadata metadata, Exception exception):在消息被应答(Acknowledgement)之前或者消息发送失败时调用,优先于用户设定的Callback之前执行。这个方法运行在Producer的IO线程中,所以这个方法里实现的代码逻辑越简单越好,否则会影响消息的发送速率。
  3. void close():关闭当前的拦截器,此方法主要用于执行一些资源的清理工作。
  4. configure(Map<String, ?> configs):用来初始化此类的方法,这个是ProducerInterceptor接口的父接口Configurable中的方法。

一般情况下只需要关注并实现onSend或者onAcknowledgement方法即可。下面我们来举个案例,通过onSend方法来过滤消息体为空的消息以及通过onAcknowledgement方法来计算发送消息的成功率。

public class ProducerInterceptorDemo implements ProducerInterceptor<String,String> {
    private volatile long sendSuccess = 0;
    private volatile long sendFailure = 0;

    @Override
    public ProducerRecord<String, String> onSend(ProducerRecord<String, String> record) {
        if(record.value().length()<=0)
            return null;
        return record;
    }

    @Override
    public void onAcknowledgement(RecordMetadata metadata, Exception exception) {
        if (exception == null) {
            sendSuccess++;
        } else {
            sendFailure ++;
        }
    }

    @Override
    public void close() {
        double successRatio = (double)sendSuccess / (sendFailure + sendSuccess);
        System.out.println("[INFO] 发送成功率="+String.format("%f", successRatio * 100)+"%");
    }

    @Override
    public void configure(Map<String, ?> configs) {}
}

自定义的ProducerInterceptorDemo类实现之后就可以在Kafka Producer的主程序中指定,示例代码如下:

public class ProducerMain {
    public static final String brokerList = "localhost:9092";
    public static final String topic = "hidden-topic";

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Properties properties = new Properties();
        properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        properties.put("bootstrap.servers", brokerList);
        properties.put("interceptor.classes", "com.hidden.producer.ProducerInterceptorDemo");

        Producer<String, String> producer = new KafkaProducer<String, String>(properties);

        for(int i=0;i<100;i++) {
            ProducerRecord<String, String> producerRecord = new ProducerRecord<String, String>(topic, "msg-" + i);
            producer.send(producerRecord).get();
        }
        producer.close();
    }
}

Kafka Producer不仅可以指定一个拦截器,还可以指定多个拦截器以形成拦截链,这个拦截链会按照其中的拦截器的加入顺序一一执行。比如上面的程序多添加一个拦截器,示例如下:

properties.put("interceptor.classes", "com.hidden.producer.ProducerInterceptorDemo,com.hidden.producer.ProducerInterceptorDemoPlus");

这样Kafka Producer会先执行拦截器ProducerInterceptorDemo,之后再执行ProducerInterceptorDemoPlus。

有关interceptor.classes参数,在kafka 1.0.0版本中的定义如下:

NAME DESCRIPTION TYPE DEFAULT VALID VALUES IMPORTANCE
interceptor.calssses A list of classes to use as interceptors. Implementing the org.apache.kafka.clients.producer.ProducerInterceptor interface allows you to intercept (and possibly mutate) the records received by the producer before they are published to the Kafka cluster. By default, there no interceptors. list null low

欢迎支持笔者新书:《RabbitMQ实战指南》以及关注微信公众号:Kafka技术专栏。
这里写图片描述

作者:u013256816 发表于2017/11/19 11:35:43 原文链接
阅读:0 评论:0 查看评论

移动Web开发基础-flexible布局方案

$
0
0

概述

前面我们已经已经了解了两种基本的布局方案,移动Web开发基础-百分比+flex布局方案移动Web开发基础-rem布局,其中rem布局方案和我们今天要了解的flexible布局方案是有关系的,因为这两种方案布局元素的单位都是rem,他们的区别在于前者是固定viewport缩放值,而flexible布局方案是根据设备像素密度比DPR动态修改viewport,下面我们来具体了解下吧。

基本了解

1.flexible布局方案是手淘团队在实际应用中总结出来的一套适配方案
2.GitHub地址:https://github.com/amfe/lib-flexible
3.详细学习参考:使用Flexible实现手淘H5页面的终端适配

理解

flexible布局方案主要处理三件事情

1.动态改写<meta>标签

这里写图片描述


2.给<html>元素添加data-dpr属性,并且动态改写data-dpr的值

3.给<html>元素添加font-size属性,并且动态改写font-size的值

如下图


这里写图片描述

这里写图片描述

从iPhone 6的设备上可以看出,淘宝约定了 1rem = 75px,如果你说计算不方便的话可以尝试去使用相应的一些插件。
因为通过viewport缩放解决了Retina显示屏倍率的问题,所以这种方案可以完美解决1像素的问题,可以直接设置边框为1px。如果你对Retina显示屏还不太了解的话可以看这里 移动Web开发基础-Viewport

data-dpr的作用是什么?

因为rem布局中,一般阅读类型的页面文字是不建议用rem作为单位的,所以我们就需要根据不同的像素密度比对同一元素设置不同的字体大小,这样更符合系统的设计原则。如下图

这里写图片描述

总结

本文主要分析了淘宝flexible布局方案的三个关键点,相信大家对原理了解清楚了之后就更容易在实践中应用它了,当然,除了目前介绍的几种布局方案之外呢,还有利用CSS3的VW、VH单位进行布局的方案,具体可以学习 大漠老师的文章 再聊移动端页面的适配

当然在使用rem布局方案的同时,也相应的可以知道一下几点内容:

1.阅读类型的页面文字尽量不用rem作为单位,因为这不符合设备系统的设计原则,也就是说不同屏幕宽度的设备,用户希望看到的是更多或更少的文字,而不是更大或更小的文字。这就好比吃红烧肉,小碗装的是小块的肉,你不能因为你换了个盆装就把红烧肉切成豆腐块那么大吧,因为用户最终希望的还是想要一小块刚刚好放嘴里的红烧肉。

2.设备最大宽度。在body元素上可以设置最大宽度,这样做的目的是为了不至于在一些特殊情况比如在PC上打开页面的时候页面上的内容非常非常大。

3.图标元素设置一定的容错空间。因为rem作为布局单位是通过计算最终转化成px作为单位的,这样有时就会因为取舍造成小数像素的误差,布局的时候还好,但是用在如雪碧图图标上时有可能出现切边,所以这种场景下可以考虑使用 iconfont或者使用 background-image时,尽量为背景图设置一定的空白间隙,如下图。

这里写图片描述

这里写图片描述

图片来源: rem 产生的小数像素问题(淘宝前端团队(FED))

另,如果想了解更多移动web开发的基础知识,可以关注我的专栏 移动Web开发实战,谢谢!

作者:u013778905 发表于2017/11/19 14:55:16 原文链接
阅读:47 评论:0 查看评论

[bzoj2761][暴力]不重复数字

$
0
0

Description

给出N个数,要求把其中重复的去掉,只保留第一次出现的数。 例如,给出的数为1 2 18 3 3 19 2 3 6 5
4,其中2和3有重复,去除后的结果为1 2 18 3 19 6 5 4。

Input

输入第一行为正整数T,表示有T组数据。 接下来每组数据包括两行,第一行为正整数N,表示有N个数。第二行为要去重的N个正整数。

Output

对于每组数据,输出一行,为去重后剩下的数字,数字之间用一个空格隔开。

Sample Input

2
11
1 2 18 3 3 19 2 3 6 5 4
6
1 2 3 4 5 6

Sample Output

1 2 18 3 19 6 5 4
1 2 3 4 5 6

HINT

对于30%的数据,1 <= N <= 100,给出的数不大于100,均为非负整数;
对于50%的数据,1 <= N <= 10000,给出的数不大于10000,均为非负整数;
对于100%的数据,1 <= N <= 50000,给出的数在32位有符号整数范围内。
提示:
由于数据量很大,使用C++的同学请使用scanf和printf来进行输入输出操作,以免浪费不必要的时间。

题解

set水过去就好了吧。。
输出小心点会PE。。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
set<int> q;
set<int>::iterator it;
int m[51000],len;
int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        q.clear();len=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            if(q.find(x)==q.end()){m[++len]=x;q.insert(x);}
        }
        for(int i=1;i<len;i++)printf("%d ",m[i]);
        printf("%d\n",m[len]);
    }
    return 0;
}
作者:Rose_max 发表于2017/11/19 15:09:01 原文链接
阅读:56 评论:0 查看评论

leetcode: 61. Rotate List

$
0
0

Q

Given a list, rotate the list to the right by k places, where k is non-negative.

Example:

Given 1->2->3->4->5->NULL and k = 2,

return 4->5->1->2->3->NULL.

AC

# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def rotateRight(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        if not head:
            return None
        n = 0
        cursor = head
        while cursor:
            cursor = cursor.next
            n += 1
        k = k%n
        if k==0: return head

        fast = slow = head
        for i in range(k):
            if fast:
                fast = fast.next
            else: 
                break
        preslow = None
        prefast = None
        while fast:
            prefast = fast
            fast = fast.next
            preslow = slow
            slow = slow.next
        if preslow:
            prefast.next = head
            preslow.next = None
            return slow
        else:
            return head


# Time:  O(n)
# Space: O(1)

# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

    def __repr__(self):
        if self:
            return "{} -> {}".format(self.val, repr(self.next))

class Solution2(object):
    def rotateRight(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        if not head or not head.next:
            return head

        n, cur = 1, head
        while cur.next:
            cur = cur.next
            n += 1
        cur.next = head

        cur, tail = head, cur
        for _ in xrange(n - k % n):
            tail = cur
            cur = cur.next
        tail.next = None

        return cur


if __name__ == "__main__":
    head, head.next, head.next.next, head.next.next.next, head.next.next.next.next = ListNode(1), ListNode(2), ListNode(3), ListNode(4), ListNode(5)
    print Solution().rotateRight(head, 2)


作者:JNingWei 发表于2017/11/19 15:26:26 原文链接
阅读:43 评论:0 查看评论

leetcode: 62. Unique Paths

$
0
0

Q

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).

How many possible unique paths are there?

Note: m and n will be at most 100.

AC

class Solution(object):
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        import math
        return math.factorial(m+n-2)/(math.factorial(m-1)*math.factorial(n-1))


# Time:  O(m * n)
# Space: O(m + n)
class Solution2(object):
    # @return an integer
    def uniquePaths(self, m, n):
        if m < n:
            return self.uniquePaths(n, m)
        ways = [1] * n

        for i in xrange(1, m):
            for j in xrange(1, n):
                ways[j] += ways[j - 1]

        return ways[n - 1]

if __name__ == "__main__":
    assert Solution().uniquePaths(1, 2) == 1


作者:JNingWei 发表于2017/11/19 15:29:45 原文链接
阅读:44 评论:0 查看评论

leetcode: 63. Unique Paths II

$
0
0

Q

Follow up for “Unique Paths”:

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.

[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]

The total number of unique paths is 2.

Note: m and n will be at most 100.

AC

class Solution(object):
    def uniquePathsWithObstacles(self, obstacleGrid):
        """
        :type obstacleGrid: List[List[int]]
        :rtype: int
        """
        m, n = len(obstacleGrid), len(obstacleGrid[0])

        ways = [0]*n
        ways[0] = 1
        for i in xrange(m):
            if obstacleGrid[i][0] == 1:
                ways[0] = 0
            for j in xrange(n):
                if obstacleGrid[i][j] == 1:
                    ways[j] = 0
                elif j>0:
                    ways[j] += ways[j-1]
        return ways[-1]


# Time:  O(m * n)
# Space: O(m + n)
class Solution2(object):
    def uniquePathsWithObstacles(self, obstacleGrid):
        """
        :type obstacleGrid: List[List[int]]
        :rtype: int
        """
        m, n = len(obstacleGrid), len(obstacleGrid[0])

        ways = [0]*n
        ways[0] = 1
        for i in xrange(m):
            if obstacleGrid[i][0] == 1:
                ways[0] = 0
            for j in xrange(n):
                if obstacleGrid[i][j] == 1:
                    ways[j] = 0
                elif j>0:
                    ways[j] += ways[j-1]
        return ways[-1]


if __name__ == "__main__":
    obstacleGrid = [
        [0,0,0],
        [0,1,0],
        [0,0,0]
    ]
    assert Solution().uniquePathsWithObstacles(obstacleGrid) == 2


作者:JNingWei 发表于2017/11/19 15:30:26 原文链接
阅读:33 评论:0 查看评论

leetcode: 64. Minimum Path Sum

$
0
0

Q

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.

Example 1:

[[1,3,1],
 [1,5,1],
 [4,2,1]]

Given the above grid map, return 7. Because the path 1→3→1→1→1 minimizes the sum.

AC


class Solution(object):
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        sum = list(grid[0])
        for j in xrange(1, len(grid[0])):
            sum[j] = sum[j - 1] + grid[0][j]

        for i in xrange(1, len(grid)):
            sum[0] += grid[i][0]
            for j in xrange(1, len(grid[0])):
                sum[j] = min(sum[j - 1], sum[j]) + grid[i][j]

        return sum[-1]


# Time:  O(m * n)
# Space: O(m + n)
class Solution2(object):
    def minPathSum(self, grid):
        sum = list(grid[0])
        for j in xrange(1, len(grid[0])):
            sum[j] = sum[j - 1] + grid[0][j]

        for i in xrange(1, len(grid)):
            sum[0] += grid[i][0]
            for j in xrange(1, len(grid[0])):
                sum[j] = min(sum[j - 1], sum[j]) + grid[i][j]

        return sum[-1]

if __name__ == "__main__":
    assert Solution().minPathSum([[0,1] ,[1,0]]) == 1
    assert Solution().minPathSum([[1,3,1], [1,5,1], [4,2,1]]) == 7


作者:JNingWei 发表于2017/11/19 15:30:55 原文链接
阅读:46 评论:0 查看评论

leetcode: 65. Valid Number

$
0
0

Q

Validate if a given string is numeric.

Some examples:
“0” => true
” 0.1 ” => true
“abc” => false
“1 a” => false
“2e10” => true
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.

Update (2015-02-10):
The signature of the C++ function had been updated. If you still see your function signature accepts a const char * argument, please click the reload button to reset your code definition.

AC

class Solution(object):
    def isNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        s = s.strip()
        if " " in s:
            return False
        if s.startswith('0') or s.lower().startswith('0b'):
            try:
                int(s, 2)
            except:
                pass
            else:
                return True
        if s.startswith('0'):
            try:
               int(s, 8)
            except:
                pass
            else:
                return True 
        if s.lower().startswith('0x'):
            try:
               int(s, 16)
            except:
                pass
            else:
                return True
        try:
           int(s, 10)
        except:
            pass
        else:
            return True
        try:
            float(s)
        except:
            pass
        else:
            return True

        return False


# Time:  O(n)
# Space: O(1)
class InputType:
    INVALID    = 0
    SPACE      = 1
    SIGN       = 2
    DIGIT      = 3
    DOT        = 4
    EXPONENT   = 5


# regular expression: "^\s*[\+-]?((\d+(\.\d*)?)|\.\d+)([eE][\+-]?\d+)?\s*$"
class Solution2(object):
    def isNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        transition_table = [[-1,  0,  3,  1,  2, -1],     # next states for state 0
                            [-1,  8, -1,  1,  4,  5],     # next states for state 1
                            [-1, -1, -1,  4, -1, -1],     # next states for state 2
                            [-1, -1, -1,  1,  2, -1],     # next states for state 3
                            [-1,  8, -1,  4, -1,  5],     # next states for state 4
                            [-1, -1,  6,  7, -1, -1],     # next states for state 5
                            [-1, -1, -1,  7, -1, -1],     # next states for state 6
                            [-1,  8, -1,  7, -1, -1],     # next states for state 7
                            [-1,  8, -1, -1, -1, -1]]     # next states for state 8

        state = 0
        for char in s:
            inputType = InputType.INVALID
            if char.isspace():
                inputType = InputType.SPACE;
            elif char == '+' or char == '-':
                inputType = InputType.SIGN
            elif char.isdigit():
                inputType = InputType.DIGIT
            elif char == '.':
                inputType = InputType.DOT
            elif char == 'e' or char == 'E':
                inputType = InputType.EXPONENT;

            state = transition_table[state][inputType];

            if state == -1:
                return False;

        return state == 1 or state == 4 or state == 7 or state == 8


class Solution3(object):
    def isNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        import re
        return bool(re.match("^\s*[\+-]?((\d+(\.\d*)?)|\.\d+)([eE][\+-]?\d+)?\s*$", s))


if __name__ == "__main__":
    assert Solution().isNumber(" 0.1 ") == True
    assert Solution().isNumber("abc") == False
    assert Solution().isNumber("1 a") == False
    assert Solution().isNumber("2e10") == True


作者:JNingWei 发表于2017/11/19 15:31:24 原文链接
阅读:29 评论:0 查看评论

leetcode: 66. Plus One

$
0
0

Q

Given a non-negative integer represented as a non-empty array of digits, plus one to the integer.

You may assume the integer do not contain any leading zero, except the number 0 itself.

The digits are stored such that the most significant digit is at the head of the list.

AC

class Solution(object):
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        c = 1
        result = []
        for i in xrange(len(digits)-1, -1 , -1):
            t = c + digits[i]

            if t >= 10:
                result.append(t % 10)
                c = 1
            else:
                result.append(t)
                c = 0

        if c == 1:
            result.append(1)
        return result[::-1]


# Time:  O(n)
# Space: O(1)
class Solution2(object):
    """
    :type digits: List[int]
    :rtype: List[int]
    """
    def plusOne(self, digits):
        carry = 1
        for i in reversed(xrange(len(digits))):
            digits[i] += carry
            carry = digits[i] / 10
            digits[i] %= 10

        if carry:
            digits = [1] + digits

        return digits

    def plusOne2(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        digits = [str(x) for x in digits]
        num = int(''.join(digits)) + 1
        return [int(x) for x in str(num)]


if __name__ == "__main__":
    assert Solution().plusOne([9, 9, 9, 9]) == [1, 0, 0, 0, 0]


作者:JNingWei 发表于2017/11/19 15:33:16 原文链接
阅读:48 评论:0 查看评论

leetcode: 67. Add Binary

$
0
0

Q

Given two binary strings, return their sum (also a binary string).

For example,
a = “11”
b = “1”
Return “100”.

AC

class Solution(object):
    def addBinary(self, a, b):
        """
        :type a: str
        :type b: str
        :rtype: str
        """
        num = int(a, 2) + int(b,2)
        return bin(num)[2:]


# Time:  O(n)
# Space: O(1)
class Solution2(object):
    def addBinary(self, a, b):
        result, carry, val = "", 0, 0
        for i in xrange(max(len(a), len(b))):
            val = carry
            if i < len(a):
                val += int(a[-(i + 1)])
            if i < len(b):
                val += int(b[-(i + 1)])
            carry, val = val / 2, val % 2
            result += str(val)
        if carry:
            result += str(carry)
        return result[::-1]


if __name__ == '__main__':
    assert Solution().addBinary('11', '1') == '100'


作者:JNingWei 发表于2017/11/19 15:34:21 原文链接
阅读:48 评论:0 查看评论

leetcode: 68. Text Justification

$
0
0

Q

Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left and right) justified.

You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces ’ ’ when necessary so that each line has exactly L characters.

Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.

For the last line of text, it should be left justified and no extra space is inserted between words.

For example,
words: [“This”, “is”, “an”, “example”, “of”, “text”, “justification.”]
L: 16.

Return the formatted lines as:

[
   "This    is    an",
   "example  of text",
   "justification.  "
]

Note: Each word is guaranteed not to exceed L in length.

Corner Cases:
A line other than the last line might contain only one word. What should you do in this case?
In this case, that line should be left-justified.

AC

class Solution(object):
    def fullJustify(self, words, maxWidth):
        """
        :type words: List[str]
        :type maxWidth: int
        :rtype: List[str]
        """
        lines = []
        i = 0
        while i<len(words):
            llen = 0  
            cur = i
            while i<len(words):
                llen += len(words[i])
                if llen>maxWidth:
                    llen -= len(words[i])
                    break
                llen+=1
                i+=1

            llen -=1
            if i != len(words):
                wordcnt = i-cur
                extra = maxWidth-llen                 
                if wordcnt>1:
                    spaces = extra/(wordcnt-1)
                    r = extra%(wordcnt-1)
                else:
                    spaces = extra
                    r = 0
            else:
                spaces = 0
                r = 0

            line = ""
            for word in words[cur:i]:
                line += word
                line += " "*(spaces+1)
                if r>0:
                    line += " "
                    r -= 1

            line = line[:maxWidth]
            if len(line)<maxWidth:
                line+=" "*(maxWidth-len(line))

            lines.append(line)

        return lines


# Time:  O(n)
# Space: O(k), k is maxWidth.
class Solution2(object):
    def fullJustify(self, words, maxWidth):
        """
        :type words: List[str]
        :type maxWidth: int
        :rtype: List[str]
        """
        def addSpaces(i, spaceCnt, maxWidth, is_last):
            if i < spaceCnt:
                return 1 if is_last else (maxWidth // spaceCnt) + int(i < maxWidth % spaceCnt)
            return 0

        def connect(words, maxWidth, begin, end, length, is_last):
            s = []  # The extra space O(k) is spent here.
            n = end - begin
            for i in xrange(n):
                s += words[begin + i],
                s += ' ' * addSpaces(i, n - 1, maxWidth - length, is_last),
            # For only one word in a line.
            line = "".join(s)
            if len(line) < maxWidth:
                line += ' ' * (maxWidth - len(line))
            return line

        res = []
        begin, length = 0, 0
        for i in xrange(len(words)):
            if length + len(words[i]) + (i - begin) > maxWidth:
                res += connect(words, maxWidth, begin, i, length, False),
                begin, length = i, 0
            length += len(words[i])

        # Last line.
        res += connect(words, maxWidth, begin, len(words), length, True),
        return res


if __name__ == "__main__":
    assert Solution().fullJustify(["This", "is", "an", "example", "of", "text", "justification."], 16) \
           == ['This    is    an', 'example  of text', 'justification.  ']


作者:JNingWei 发表于2017/11/19 15:34:44 原文链接
阅读:50 评论:0 查看评论

leetcode: 69. Sqrt(x)

$
0
0

Q

Implement int sqrt(int x).

Compute and return the square root of x.

x is guaranteed to be a non-negative integer.

Example 1:

Input: 4
Output: 2

Example 2:

Input: 8
Output: 2
Explanation: The square root of 8 is 2.82842..., and since we want to return an integer, the decimal part will be truncated.

AC

class Solution(object):
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        if x==0:return 0
        if x==1:return 1
        start = 1
        end = x
        last = -1
        while True:
            mid = (start+end)/2
            if mid==last:
                return mid
            if mid**2 == x:
                return mid
            elif mid**2<x:
                start = mid
            else:
                end = mid
            last = mid


# Time:  O(logn)
# Space: O(1)
class Solution2(object):
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        if x < 2:
            return x

        left, right = 1, x // 2
        while left <= right:
            mid = left + (right - left) // 2
            if mid > x / mid:
                right = mid - 1
            else:
                left = mid + 1

        return left - 1


if __name__ == "__main__":
    assert Solution().mySqrt(10) == 3


作者:JNingWei 发表于2017/11/19 15:35:11 原文链接
阅读:45 评论:0 查看评论

TensorFlow发布eager,便于debug!

$
0
0

要查看网络中间结果,使用TensorFlow的小伙伴都知道,必须要run一下session,返回对应的值才能查看,这是很不方便的。为此,TensorFlow团队发布了eager,可以实时查看中间结果,便于大家Debug。那么怎么来用呢?今天简单介绍一下。

1. 安装

Eager execution还没有包含在最新的1.4版本中,所以使用pip安装的TF没有eager。有两个办法可以安装,一是本地编译安装TensorFlow 1.4,可以生成eager。二是安装轻量级的库:

pip install tf-nightly # (for CPU-only TensorFlow)
pip install tf-nightly-gpu # (for GPU-enabled TensorFlow)

2. 使用

import tensorflow.contrib.eager as tfe
tfe.enable_eager_execution()

在头文件中import eager库,并激活eager execution,后面默认eager一直处于激活状态。这个时候,中间结果像numpy结构的数据一样,可以直接打印输出。



此外,还有一个优势,tensor和numpy可以自动互相调用。

import numpy as np

np_x = np.array(2., dtype=np.float32)
x = tf.constant(np_x)

py_y = 3.
y = tf.constant(py_y)

z = x + y + 1

print(z)
print(z.numpy())

# Output
tf.Tensor(6.0, shape=(), dtype=float32)
6.0
这个真的展示了TF的特点,快速,灵活!



更多资料,请查看:

TensorFlow Eager Execution



作者:helei001 发表于2017/11/19 16:00:56 原文链接
阅读:79 评论:0 查看评论

lua学习笔记——文件I/O

$
0
0

1、lua中的文件I/O
lua的文件I/O有两种模式,分别是简单模式和完全模式,他们的区别如下:
简单模式:只有一个默认输入文件和一个默认输出文件,并且提供对这些文件的操作。
完全模式:使用外部的文件句柄来实现。它以一种面向对象的形式,将所有文件操作定义为文件句柄的方法。完全模式可以同时对多个文件进行操作。

2、打开和关闭文件
打开文件:file=io.open(filename,mode)
mode的值可以是:
这里写图片描述

关闭文件:io.close(file)

3、简单模式
简单模式使用标准的I/O操作,简单模式下只有一个默认输入文件和一个输出文件
例:文件操作函数
这里写图片描述

在简单模式下,同一时间只能对一个文件进行操作。在上面的例子当中,io.read()函数没有带参,实际上read函数可以有参数的,如下:
这里写图片描述

4、完全模式
通常我们需要在同一时间处理多个文件,我们需要使用file:function_name来代替io.function_name方法。即将文件操作定义为文件句柄的方法。
例:
这里写图片描述

5、其他的io方法
io.tmpfile():返回一个临时文件句柄,该文件以更新模式打开,程序结束时自动删除。
io.type(file):检测file是否是一个可用文件句柄
io.flush():刷新缓冲区。
io.lines(file name):打开指定的文件为读模式,并返回一个迭代函数,每次调用将获得文件中的一行内容,当到文件尾时,将返回nil,但不关闭文件。
file:flush():刷新缓冲区。
file:seek(whence,offset):设置和获取当前文件位置,其中whence的值可以是“set”(从文件头开始),“cur”(从当前位置开始),“end”(从文件结尾开始)。

例:一行一行的读取文件全部内容
这里写图片描述

作者:LF_2016 发表于2017/11/19 16:12:20 原文链接
阅读:18 评论:0 查看评论

Advanced Programming in UNIX Environment Episode 17

$
0
0

rename和renameat函数

#include <stdio.h>

int rename(const char *oldname, const char *newname);
int renameat(int oldfd, const char *oldname, int newfd, const char *newname);

引入符号链接的原因是为了避开硬链接的一些限制。

  • 硬链接通常要求链接和文件位于同一文件系统中
  • 只有超级用户才能创建指向目录的硬链接

    用symlink或symlinkat函数创建一个符号链接。

#include <unistd.h>

int symlink(const char *actualpath, const char *sympath);
int symlinkat(const char *actualpath, int fd, const char *sympath);

打开该链接本身,并读取该链接中的名字。readlink和readlinkat函数提供了这种功能。

#include <unistd.h>

ssize_t readlink(const char *restrict pathname, char *restrict buf, size_t bufsize);
ssize_t readlinkat(int fd, const char *restrict pathname, char *restrict buf, size_t bufsize);

futimens和utimensat函数可以指定纳秒级精度的时间戳。

#include <unistd.h>

int futimes(int fd, const struct timespec times[2]);
int utimensat(int fd, const char *path, const struct timespec times[2], int flag);

futimes和utimensat函数都包含在POSIX.1中,第3个函数utimes包含在Single UNIX Specification的XSI扩展中。

#include <sys/time.h>

int utimes(const char *pathname, const struct timeval times[2])
作者:myfather103 发表于2017/11/19 16:17:56 原文链接
阅读:22 评论:0 查看评论

[bzoj 1079--SCOI2008]着色方案

$
0
0

有n个木块排成一行,从左到右依次编号为1~n。你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块。
所有油漆刚好足够涂满所有木块,即c1+c2+…+ck=n。相邻两个木块涂相同色显得很难看,所以你希望统计任意两个相邻木块颜色不同的着色方案。

真是一道大神题啊。一开始看到时乱想一大推,但其实原来这题如此巧妙。
其实像这样统计方案的问题,一般就是用dp来做的,只不过这题dp用记忆化搜索罢了。
先定义一个f数组,f[a1][a2][a3][a4][a5][x]中ai表示还剩下i次机会涂色的颜色种类数,x表示上一次涂色用的是a几。为什么这样呢,因为决定现在这个颜色是否能涂只跟上一次涂色有关。
那么问题来了,如何快速继承状态呢?
首先得弄明白一点,当前选什么样的颜色不重要,只需满足相邻条件就行,还剩下多少次能涂才是重要的。举个例子,假设你要选还剩下3次机会涂色的颜色,只需让a3(或a3-1,为什么等一下讲)乘上f[a1][a2+1][a3-1][a4][a5][x](为什么等一下讲)就行。
明白后就方便继承了。但还有几点需要注意,假设你选了还剩下3次机会涂色的颜色,那你a2就要+1,a3要-1,因为你选了以后它就变成了还剩下2次机会涂色的颜色。相邻条件似乎是最大的难点,但我们知道了你上次选了还剩下i次机会涂色的颜色,如果你这次要选还剩下i-1次机会涂色的颜色,那你就不能再选上次选过的颜色,不然会相邻,这就是a(i-1)-1乘而不是a(i-1)乘的原因。
那么这题便迎刃而解了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#define mod 1000000007
using namespace std;
int s[6];
long long f[17][17][17][17][17][7];
long long dfs(int a1,int a2,int a3,int a4,int a5,int x)
{
    if(a1==0 && a2==0 && a3==0 && a4==0 && a5==0)f[a1][a2][a3][a4][a5][x]=1;
    if(f[a1][a2][a3][a4][a5][x]!=0)return f[a1][a2][a3][a4][a5][x];
    long long ans=0;
    if(a1!=0)
    {
        int he=a1;if(x==2)he--;
        ans+=he*dfs(a1-1,a2,a3,a4,a5,1);ans%=mod;
    }
    if(a2!=0)
    {
        int he=a2;if(x==3)he--;
        ans+=he*dfs(a1+1,a2-1,a3,a4,a5,2);ans%=mod;
    }
    if(a3!=0)
    {
        int he=a3;if(x==4)he--;
        ans+=he*dfs(a1,a2+1,a3-1,a4,a5,3);ans%=mod;
    }
    if(a4!=0)
    {
        int he=a4;if(x==5)he--;
        ans+=he*dfs(a1,a2,a3+1,a4-1,a5,4);ans%=mod;
    }
    if(a5!=0)
    {
        int he=a5;
        ans+=he*dfs(a1,a2,a3,a4+1,a5-1,5);ans%=mod;
    }
    f[a1][a2][a3][a4][a5][x]=ans;
    return ans;
}
int main()
{
    int k;
    scanf("%d",&k);
    for(int i=1;i<=k;i++)
    {
        int x;
        scanf("%d",&x);
        s[x]++;
    }
    printf("%lld\n",dfs(s[1],s[2],s[3],s[4],s[5],0));
    return 0;
}
作者:lixuanjing2016 发表于2017/11/19 16:44:13 原文链接
阅读:39 评论:0 查看评论

git权威指南总结七:git merge冲突解决

$
0
0

git pull拉回操作中的合并

在前面一个博客,我们将到了非快进式推送的非强制性的另一种解决办法,那就是先拉回在提交,这里的拉回其实包含了两个操作:获取远程仓库的数据,将本地数据进行合并。可以这样写:git pull = git fetch + git merge
git merge命令用于合并分支,它的命令行格式为:git merge [options...] <commit>...大多数情况下的合并我们只需要提供一个commit分支就可以了,默认将指定分支合并到当前分支中。合并后的提交以当前分支的提交作为第一个父提交,以为第二个父提交,合并操作也支持多个与当前工作分支进行合并
默认情况下,合并后的结果会自动提交,我们可以通过设置选项来指定手动提交,通过命令:git merge --no-commit <commit>...模式可以指定合并先将结果放入暂存区,让用户手动对合并结果进行检查、更改,然后手动提交
合并操作并非总会成功,下面将详细介绍


合并一:自动合并

这一类合并不会报错,不需要用户来处理相应的错误,主要分为三种
修改不同的文件
如果两个(或者多个,这里只介绍两个)用户user1/user2各自的本地提交中修改的是不同的文件,那么第二次进行合并推送的提交将能正确合并并提交,不会遇到任何麻烦
修改相同文件的不同区域
首先需要说明的是,文件的修改是分区域的,可以具体到修改哪一行,通过命令cat > fileName.suffix进行逐行修改
当user1用户修改了index.txt文件的第一行第二行并进行提交与上游推送,然后user2用户同样修改了index.txt文件,不过修改的是第三行和第四行,然后在进行git pull命令,同样能正常合并,不会遇到任何麻烦
同时更改文件名和文件内容
如果user1用户将index.txt文件移动到了index2.txt文件并删除index.txt(重命名的操作),并且进行了提交与上游推送,此时user2用户使用命令git pull获取并合并信息之后,会发现它同样也能正常合并,然后我们进行推送:git push origin master然后成功推送,接着我们查看一下远程仓库的内容,会发现git对这种情况的处理方式是:user2用户最终修改的是user1用户对应重命名后的文件
这种情况下的自动合并其实是有逻辑冲突的,就C语言编程我们来举一个例子:我们在main.c文件中调用了一个头文件head.h文件,然后另一个用户将该文件该名成head2.h文件,最终我们使用main.c文件将会编译错误:找不到head.h头文件。所以在这种情况下,我们要慎重合并,或者在本次提交操作上添加一些重要的注释


合并二:冲突解决

当两个用户同时修改同一个文件的相同区域的内容时,就会发生冲突事件了。看如下例子:
首先为了保证两个用户的本地版本库和远程版本库一直,分别进行命令:git pull
然后先将user1用户修改文件hello.txt成如下内容并进行提交:

这里写图片描述
这里写图片描述

然后user2用户进行同样的修改操作如下:

这里写图片描述

接下来我们进行user2用户的非快进式合并推送,会发现合并失败:

这里写图片描述

这就是因为两个用户同时修改了相同文件的相同区域造成的冲突,通过命令查看当前状态,会发现输出的日志告诉我们同时修改了一个文件hello.txt

这里写图片描述

接下来我们通过一个命令来查看到底是哪些文件发生了合并冲突,这个命令是:git ls-files -s该命令输出的第二列的值如果为0表示对应的文件没有冲突,合并成功,如果不为0,则表示产生了合并的冲突,其中具体的值对应的意义是:1表示两个用户之前一个共同版本的对应文件内容;2表示当前用户对应的文件版本;3表示合并后的文件对应的远程版本

这里写图片描述

通过命令:git show :n:filename查看对应文件的对应版本的内容

这里写图片描述

在知道了三个版本的文件内容之后,我们就可以手动的对冲突的文件进行手动修改操作了。这里需要注意的是,对应的冲突文件的内容已经发生了改变,里面对应的冲突区域的内容将会同时存在当前分支的内容和远程版本的内容,如下图。我们可以手动对该文件进行修改操作,然后在手动add、commit、push就可以了

这里写图片描述

然后我们通过之前的查看版本区别的命令就可以看到对应的冲突文件已经没有冲突了

这里写图片描述

对于上面的文件冲突,除了通过使用命令git ls-files -s // git show :n:filename来解决之外,还可以通过git内置的图形化界面工具来操作,通过命令:git mergetool打开工具,默认git提供的是kdiff3,其中上方的三个界面从左到右依次为:两个版本的前一个共同版本的文件版本、当前本地版本的文件版本、合并后的文件版本


合并三:树冲突

如果一个用户将某个文件进行改名,而另一个用户也对该文件进行改名,当这两个用户的提交进行合并操作时,就会发生树冲突,因为git无法替用户做选择。下面将对树冲突进行测试并给出解决办法
同样为了确保两个用户的当前版本信息和远程版本一直,分别对两个用户执行命令:git pull
首先user1用户将hello.txt文件改名成user1.txt

这里写图片描述

然后进行提交

这里写图片描述

接下来user2用户对相同的hello.txt文件进行改名成user2.txt

这里写图片描述

然后进行user2用户推送后提交

这里写图片描述

然后发现合并出现了冲突,这是因为多个用户修改了相同的文件的文件名,查看当前分支的状态

这里写图片描述

我们可以通过命令:git ls-files -s查看当前版本的冲突文件对应的状态,其中1表示当前合并前的版本的文件对应的文件名,2表示当前分支的文件名,3表示合并的版本的文件名

这里写图片描述

同样我们知道了这些信息之后就可以进行手动修改操作了。首先,删除需要改名的对应的文件,这里就是删除文件hello.txt,然后删除user1.txt文件或者删除user2.txt文件即可进行提交和上游注册了


合并策略概述

git合并操作可以指定使用的合并策略,默认会选择最适合的合并策略。例如:两个分支的合并默认使用recursive合并策略、两个以上分支的合并默认使用octpus合并策略。我们也可以通过传递参数来指定使用的合并策略,命令行模式为:gig merge -s 合并策略 -x 合并策略参数 <commit>...
resolve策略:只能用于两个分支的合并,这个合并策略被认为是最安全、最快的合并策略
recursive策略:只能用于两个分支的合并,两个分支的合并默认使用该策略。该策略可以使用选项:
ours:在遇到冲突的时候,选择当前分支的版本,而忽略远程合并过来的版本。
theirs:和ours选项相反
subtree[=path]:使用子树合并策略
octpus策略:用于合并两个以上分支的策略,该策略拒绝执行需要手动解决的复杂合并。
ours:可以用于任意多个分支的合并策略,合并的结果总是使用当前分支的内容而丢弃远程合并过来的版本内容
subtree:这是一个经过调整后的recursive策略,子树合并策略相关内容可以去百度,这里就不详解了(主要是博主也不会~~)


合并相关的设置

可以通过命令git config来设置与合并相关的配置变量,对合并进行配置。
merge.conflictstyle:该配置变量定义冲突文件中冲突内容的标记风格,有两个可用的风格:默认的merge和diff3
默认的merge风格使用标准的冲突分界符<<<<<<<=======>>>>>>>读冲突内容进行标识,两个文字块分别是本地的修改和他人的修改
diff3风格会在冲突文件中出现三个文字块,<<<<<<< ||||||| ======= >>>>>>>,分别表示本地更改版本、共同的原始版本、他人更改的版本
merge.tool:设置执行命令git mergetool进行冲突解决时调用的图形化工具
merge..path:设置对应的图形化工具的安装位置


参考文献

git权威指南一书
作者:qq_27905183 发表于2017/11/19 16:47:52 原文链接
阅读:30 评论:0 查看评论

LWC 59:728. Self Dividing Numbers

$
0
0

LWC 59:728. Self Dividing Numbers

传送门:728. Self Dividing Numbers

Problem:

A self-dividing number is a number that is divisible by every digit it contains.

For example, 128 is a self-dividing number because 128 % 1 == 0, 128 % 2 == 0, and 128 % 8 == 0.

Also, a self-dividing number is not allowed to contain the digit zero.

Given a lower and upper number bound, output a list of every possible self dividing number, including the bounds if possible.

Example 1:

Input:
left = 1, right = 22
Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 22]

Note:

  • The boundaries of each input argument are 1 <= left <= right <= 10000.

思路:
非常直观,对每个num,进行拆分判断,合法加入集合,不合法忽略。

一版本:

    public List<Integer> selfDividingNumbers(int left, int right) {
        List<Integer> ans = new ArrayList<>();
        for (int i = left; i <= right; ++i) {
            if (valid(i)) {
                ans.add(i);
            }
        }
        return ans;
    }

    boolean valid(int num) {
        String value = Integer.toString(num);
        for (char c : value.toCharArray()) {
            if (c == '0') return false;
            else {
                if (num % (c - '0') != 0) return false;
            }
        }
        return true;
    }

二版本:

    public List<Integer> selfDividingNumbers(int left, int right) {
        List<Integer> ans = new ArrayList<>();
        for (int i = left; i <= right; ++i) {
            if (valid(i)) {
                ans.add(i);
            }
        }
        return ans;
    }

    boolean valid (int num) {
        int n = num;
        while (num != 0) {
            int c = num % 10;
            if (c == 0) return false;
            else {
                if (n % c != 0) return false;
            }
            num /= 10;
        }
        return true;
    }
作者:u014688145 发表于2017/11/19 16:53:11 原文链接
阅读:27 评论:0 查看评论

FZU_2216 The Longest Straight (二分)

$
0
0
Problem 2216 The Longest Straight

Accept: 441    Submit: 1380
Time Limit: 1000 mSec    Memory Limit : 32768 KB

Problem Description

ZB is playing a card game where the goal is to make straights. Each card in the deck has a number between 1 and M(including 1 and M). A straight is a sequence of cards with consecutive values. Values do not wrap around, so 1 does not come after M. In addition to regular cards, the deck also contains jokers. Each joker can be used as any valid number (between 1 and M, including 1 and M).

You will be given N integers card[1] .. card[n] referring to the cards in your hand. Jokers are represented by zeros, and other cards are represented by their values. ZB wants to know the number of cards in the longest straight that can be formed using one or more cards from his hand.

Input

The first line contains an integer T, meaning the number of the cases.

For each test case:

The first line there are two integers N and M in the first line (1 <= N, M <= 100000), and the second line contains N integers card[i] (0 <= card[i] <= M).

Output

For each test case, output a single integer in a line -- the longest straight ZB can get.

Sample Input

2

7 11
0 6 5 3 0 10 11

8 1000
100 100 100 101 100 99 97 103

Sample Output

5

3

Source

第六届福建省大学生程序设计竞赛-重现赛(感谢承办方华侨大学)

有n个数,0可以变成1到M之间的任意一个数,求最长能连续的数。

因为m和a【i】的值最大为100000,所以跑数组下标比较方便,然后就是求所有的区间中需要填充的数量,找到数量适合并且区间最长的区间输出。
所以输入的数据要统计0的个数,把输入的每一个值当下标,进行标记,用一个数组来记录到当前值所需要0的个数,下面的难题就是求所有区间所需要的0的个数。

因为m=100000,所以最大区间的端点都已经确定,不妨二分找区间,每次维护最大值,最后输出结果。

二分时令l=i,r=m,如果ans[mid-ans[i]==0的不要返回,此时继续缩小左区间,以便于求的r的最大值,退出二分时的r-i就是以i为左端点,m为右端点,满足0的个数的区间长度,然后维护最大区间长度,得到结果。

时间复杂度 O(mlogm)

代码实现:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<cstdio>
#define ll long long
#define mset(a,x) memset(a,x,sizeof(a))

using namespace std;
const double PI=acos(-1);
const int inf=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int mod=1e9+7;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;}
ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;}
int map[100005],ans[100005];

int main()
{
	int n,m,i,j,k,t,x;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		mset(map,0);
		mset(ans,0);
		int sum=0;
		for(i=0;i<n;i++)
		{
			scanf("%d",&x);
			if(x==0)
			sum++;
			else
			map[x]=1;
		} 
		for(i=1;i<=m;i++)
		{
			if(map[i])
			ans[i]=ans[i-1];
			else
			ans[i]=(ans[i-1]+1);
		}
		int maxx=0;
		for(i=0;i<=m;i++)
		{
			int l=i,r=m,mid;
			while(l<=r)
			{
				mid=(l+r)/2;
				if(ans[mid]-ans[i]>sum)
				r=mid-1;
				else
				l=mid+1;
			}
			maxx=max(maxx,r-i);
		}
		cout<<maxx<<endl;
	}
	return 0;
}


作者:Ever_glow 发表于2017/11/19 17:22:57 原文链接
阅读:24 评论:0 查看评论
Viewing all 35570 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>