├── .idea ├── dictionaries │ └── L1n.xml └── vcs.xml ├── C_问答题汇总.md ├── Python 语言特性 ├── 1 Python的函数参数传递.md ├── 2 @staticmethod和@classmethod.md ├── 3 类变量和实例变量.md ├── 4 Python中单下划线和双下划线.md ├── 5 args and kwargs.md ├── 6 面向切面编程AOP和装饰器.md ├── 7 单例模式.md ├── 8 Python 函数式编程.md ├── 9 Python 里的拷贝.md └── readme.md ├── Python 面试编程题 ├── 1 台阶问题 斐波那契 │ ├── fibonacci.py │ ├── unittest_fibonacci.py │ └── 斐波那契.md ├── 10 快排 │ ├── qsort.py │ ├── unittest_sort.py │ └── 快排.md ├── 11 找零问题 │ ├── coin_change.py │ └── 找零问题.md ├── 12 二叉树相关 │ ├── binary_tree.py │ └── 二叉树相关.md ├── 13 单链表逆置 │ ├── single_list_reverse.py │ └── 单链表逆置.md ├── 2 变态台阶问题 │ ├── similar_frog_jump.py │ └── 变态台阶问题.md ├── 3 矩形覆盖 │ ├── rectangle.py │ └── 矩阵覆盖.md ├── 4 杨氏矩阵查找 │ ├── rectangle_search.py │ ├── unittest_rectangle_search.py │ └── 杨氏矩阵查找.md ├── 5 去除列表中的重复元素 │ ├── delete_repeat.py │ └── 去除列表中的重复元素.md ├── 6 链表成对调换 │ ├── swap_pairs_list_node.py │ └── 链表成对调换.md ├── 7 创建字典的方法 │ ├── create_dict.py │ └── 创建字典的方法.md ├── 8 合并两个有序列表 │ ├── merge_sort.py │ ├── unittest_merge_sort.py │ └── 合并两个有序列表.md ├── 9 二分查找 │ ├── binary_search.py │ ├── unittest_binary_search.py │ └── 二分查找.md └── readme.md ├── README.md ├── SUMMARY.md ├── python_script ├── check_summary.py ├── readme.md ├── search_keyword.py └── test_check_summary.py ├── stackoverflow-about-Python ├── Python中关键字yield有什么作用.md ├── Python中如何在一个函数中加入多个装饰器.md ├── Python中的元类(metaclass)是什么.md ├── join的问题.md ├── name=main的作用.md ├── readme.md ├── str与repr的区别.md ├── super与init方法.md ├── 为什么代码在一个函数里运行的更快.md ├── 为什么用pip比用easy_install的好.md ├── 单下划线和双下划线的含义.md ├── 变化的默认参数.md ├── 在Android上运行Python.md ├── 在Windows下安装pip.md ├── 在函数里使用全局变量.md ├── 如何判断一个文件是否存在.md ├── 如何知道一个对象有一个特定的属性.md ├── 如何调用外部命令.md ├── 如何通过函数名的字符串来调用函数.md ├── 字典合并问题.md ├── 循环中获取索引.md ├── 快速合并列表中的列表.md ├── 怎么在终端里输出颜色.md ├── 怎么用引用来改变一个变量.md ├── 把列表分割成同样大小的块.md ├── 枚举类型的使用.md ├── 根据字典值进行排序.md ├── 检查列表为空的最好办法.md ├── 检查文件夹是否存在的操作.md ├── 类里的静态变量.md └── 装饰器classmethod和staticmethod的区别.md ├── 剑指 Offer 编程题 ├── readme.md ├── 二维数组中的查找 │ ├── python_solve.py │ ├── readme.md │ └── unittest_solve.py ├── 从尾到头打印链表 │ ├── python_solve.py │ └── readme.md ├── 旋转数组的最小数字 │ └── readme.md ├── 替换空格 │ └── readme.md ├── 用两个栈实现队列 │ ├── readme.md │ └── two_stack_implement_queue.py └── 重建二叉树 │ ├── readme.md │ └── rebuild_binary_tree_pre_in_order.py ├── 安全测试开发相关面试 ├── readme.md ├── 业务安全类面试参考.md ├── 安全测试类面试参考.md ├── 测试开发类面试参考.md ├── 测试开发类面试参考2.md ├── 测试开发类面试参考3.md ├── 测试类HR面参考.md └── 测试类综合面试参考.md ├── 深信服_sangfor_相关 ├── readme.md ├── sangfor_acm_oj │ ├── 2016_12_03 │ │ ├── A.py │ │ ├── C.py │ │ ├── C_ACM │ │ │ ├── out(2).zip │ │ │ ├── right_C_answer.zip │ │ │ ├── sxf.cpp │ │ │ ├── sxf1.cpp │ │ │ ├── sxf22.cpp │ │ │ └── test——A.txt │ │ ├── out.zip │ │ ├── template.py │ │ ├── test_A.py │ │ ├── test_A.txt │ │ ├── test_C.zip │ │ └── test_C_answer.zip │ ├── before_2016_12_03 │ │ ├── __init__.py │ │ ├── acm_1001.py │ │ ├── acm_1003.py │ │ ├── acm_1004.py │ │ ├── acm_1005.py │ │ ├── acm_1076.py │ │ ├── acm_1077.py │ │ ├── acm_1078.py │ │ ├── acm_1079.py │ │ ├── acm_1080.py │ │ ├── acm_1081.py │ │ ├── acm_1082.py │ │ ├── acm_1083.py │ │ ├── acm_1084.py │ │ ├── acm_1085.py │ │ ├── acm_1086.py │ │ ├── acm_1087.py │ │ ├── acm_1088.py │ │ ├── acm_1089.py │ │ ├── acm_1090.py │ │ ├── acm_1091.py │ │ ├── acm_1092.py │ │ ├── acm_1093.py │ │ ├── acm_1094.py │ │ ├── test_1003.py │ │ ├── test_1004.py │ │ └── test_1005.py │ └── readme.md ├── 智安全杯 │ ├── 2018比赛.md │ ├── 2019初赛.md │ ├── 2019复赛.md │ └── readme.md └── 测试类面试参考.md ├── 编程题汇总.md ├── 网易 2017 校招笔试编程题 ├── binary_weight.py ├── readme.md ├── test_binary_weight.py ├── 二进制权重.md ├── 平方串.md └── 数位和.md ├── 腾讯 2017 暑期实习生编程题 ├── README.md ├── get_longest_palindromic_substring.py ├── 字符移位 │ ├── readme.md │ └── solve.py ├── 有趣的数字.md ├── 有趣的数字 │ ├── readme.md │ ├── solve.py │ └── unittest_solve.py ├── 构造回文.md ├── 构造回文 │ ├── get_longest_palindromic_substring.py │ ├── readme.md │ └── solve.py ├── 算法基础-字符移位.md └── 腾讯 2017 暑期实习生编程题.md ├── 计算机知识 ├── readme.md ├── readme1.md ├── readme2.md └── readme3.md └── 软件测试题 └── 题目汇总.md /.idea/dictionaries/L1n.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | stackoverflow 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Python 语言特性/1 Python的函数参数传递.md: -------------------------------------------------------------------------------- 1 | ```Python 2 | #!/bin/env python3 3 | # -*- coding: utf-8 -*- 4 | # version: Python3.X 5 | """ 参考网上资料, 关于 Python 的函数参数传递问题 6 | 7 | 总结: 8 | 在 Python 中, strings, tuples, numbers 是不可更改的对象, 而 list, dict 等则是可以修改的对象 9 | """ 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | def modify_fun_fail(value): 15 | """ 16 | 当一个引用传递给函数的时候, 函数自动复制一份引用, 这个函数里的引用和外边的引用没有关系 17 | 所以这里函数把引用指向了一个不可变对象, 当函数返回的时候, 外面的引用不会被改变 18 | :param value: int() 19 | :return: None 20 | """ 21 | value += 50 22 | print("调用函数 {}, 修改值为 {}".format("modify_fun_fail", value)) 23 | 24 | 25 | def modify_fun_success(a_list): 26 | """ 27 | 函数内的引用指向的是可变对象, 对它的操作就和定位了指针地址一样, 在内存里进行修改 28 | :param a_list: list() 29 | :return: None 30 | """ 31 | a_list.append(1) 32 | print("调用函数 {}, 修改值为 {}".format("modify_fun_success", a_list)) 33 | 34 | 35 | if __name__ == "__main__": 36 | number = 30 37 | print("接下来调用函数 {}, 当前 number 值为 {}".format("modify_fun_fail", number)) 38 | modify_fun_fail(number) 39 | print("调用完成, number 值为 {}".format(number), end="\n\n") 40 | 41 | number_list = list() 42 | print("接下来调用函数 {}, 当前 number_list 值为 {}".format("modify_fun_success", number_list)) 43 | modify_fun_success(number_list) 44 | print("调用完成, number_list 值为 {}".format(number_list)) 45 | ``` -------------------------------------------------------------------------------- /Python 语言特性/2 @staticmethod和@classmethod.md: -------------------------------------------------------------------------------- 1 | ```Python 2 | #!/bin/env python3 3 | # -*- coding: utf-8 -*- 4 | # version: Python3.X 5 | """ Python 有 4 个方法, 静态方法(staticmethod), 类方法(classmethod), 实例方法, 普通方法 6 | """ 7 | 8 | __author__ = '__L1n__w@tch' 9 | 10 | 11 | def normal_function(): 12 | print("I am just a 普通方法") 13 | 14 | 15 | class FunctionTest: 16 | def method(self, value): 17 | """ 18 | self 是对实例的绑定, 需要把实例自己传给函数, 调用的时候是这样的 ft.method(value), 其实是 method(ft, value) 19 | :param value: int() 20 | :return: None 21 | """ 22 | print("I am just a 实例方法, {}; {}".format(self, value)) 23 | 24 | @classmethod 25 | def class_method(cls, value): 26 | """ 27 | # cls是对类的绑定 28 | :param value: int() 29 | :return: None 30 | """ 31 | print("I am just a 类方法, {}; {}".format(cls, value)) 32 | 33 | @staticmethod 34 | def static_method(value): 35 | print("I am just a 静态方法, 打印值 {}".format(value)) 36 | 37 | 38 | if __name__ == "__main__": 39 | ft = FunctionTest() 40 | 41 | normal_function() 42 | 43 | ft.method(3.4) 44 | ft.static_method(3.4) 45 | ft.class_method(3.4) 46 | 47 | FunctionTest.static_method(3.4) 48 | FunctionTest.class_method(3.4) 49 | ``` -------------------------------------------------------------------------------- /Python 语言特性/3 类变量和实例变量.md: -------------------------------------------------------------------------------- 1 | ```Python 2 | #!/bin/env python3 3 | # -*- coding: utf-8 -*- 4 | # version: Python3.X 5 | """ 关于类变量和实例变量的讨论 6 | """ 7 | 8 | __author__ = '__L1n__w@tch' 9 | 10 | 11 | class VarTest: 12 | str_var = "I am 类变量" 13 | list_var = ["I am 类变量"] 14 | 15 | 16 | if __name__ == "__main__": 17 | vt1 = VarTest() 18 | vt2 = VarTest() 19 | 20 | vt1.str_var = "I am 实例变量" 21 | print("vt1.str_var: {}".format(vt1.str_var)) 22 | print("vt2.str_var: {}".format(vt2.str_var)) 23 | print("VarTest.str_var: {}".format(VarTest.str_var), end="\n\n") 24 | 25 | # 在实例的作用域里把类变量的引用改变了, 就变成了一个实例变量, self.list_var 不再引用 VarTest 的类变量 list_var 了 26 | vt1.list_var.append("vt1 到此一游") 27 | print("vt1.list_var: {}".format(vt1.list_var)) 28 | print("vt2.list_var: {}".format(vt2.list_var)) 29 | print("VarTest.list_var: {}".format(VarTest.list_var)) 30 | ``` -------------------------------------------------------------------------------- /Python 语言特性/4 Python中单下划线和双下划线.md: -------------------------------------------------------------------------------- 1 | ```Python 2 | #!/bin/env python3 3 | # -*- coding: utf-8 -*- 4 | # version: Python3.X 5 | """ 讨论关于单下划线和双下划线命名的问题 6 | 7 | 总结: 8 | __foo__:一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突. 9 | _foo:一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式. 10 | __foo:这个有真正的意义:解析器用_className__foo来代替这个名字,以区别和其他类相同的命名. 11 | """ 12 | 13 | __author__ = '__L1n__w@tch' 14 | 15 | 16 | class UnderlineTest: 17 | def __init__(self): 18 | self.__super_private = "超级私有" 19 | self._semi_private = "假私有" 20 | 21 | 22 | if __name__ == "__main__": 23 | ut = UnderlineTest() 24 | try: 25 | print(ut.__super_private) 26 | except AttributeError as e: 27 | print("[!] 找不到超级私有") 28 | print(e) 29 | 30 | print("寻找假私有{}: {}", "ut._semi_private", ut._semi_private) 31 | print("打印 __dict__: {}".format(ut.__dict__)) 32 | ``` -------------------------------------------------------------------------------- /Python 语言特性/5 args and kwargs.md: -------------------------------------------------------------------------------- 1 | ```Python 2 | #!/bin/env python3 3 | # -*- coding: utf-8 -*- 4 | # version: Python3.X 5 | """ 讨论关于 args 和 kwargs 的相关知识点 6 | 7 | 总结: 8 | 当你不确定你的函数里将要传递多少参数时你可以用 *args 9 | **kwargs 允许你使用没有事先定义的参数名 10 | 可以混着用, 命名参数首先获得参数值然后所有的其他参数都传递给 *args 和 **kwargs 11 | 12 | """ 13 | 14 | __author__ = '__L1n__w@tch' 15 | 16 | 17 | def test_args(*args): 18 | # 当你不确定你的函数里将要传递多少参数时你可以用 *args 19 | for count, value in enumerate(args): 20 | print("{}: {}".format(count, value)) 21 | 22 | 23 | def test_kwargs(**kwargs): 24 | # **kwargs 允许你使用没有事先定义的参数名 25 | for key, value in kwargs.items(): 26 | print("Key:Value, {}:{}".format(key, value)) 27 | 28 | 29 | # 当调用函数时你也可以用 * 和 ** 语法 30 | def star_operation(name, value, count): 31 | print("Name: {}, Value: {}, Count: {}".format(name, value, count)) 32 | 33 | 34 | if __name__ == "__main__": 35 | test_args("a", "1", "c", "b", "3", "2") 36 | test_kwargs(test1=1, test2=2, test3=3) 37 | 38 | # 它可以传递列表(或者元组)的每一项并把它们解包. 注意必须与它们在函数里的参数相吻合 39 | a_list = ["名字", "值", "计数器"] 40 | star_operation(*a_list) 41 | ``` -------------------------------------------------------------------------------- /Python 语言特性/6 面向切面编程AOP和装饰器.md: -------------------------------------------------------------------------------- 1 | ```Python 2 | #!/bin/env python3 3 | # -*- coding: utf-8 -*- 4 | # version: Python3.X 5 | """ 练习一下自己怎么写一个装饰器 6 | 7 | 完整资料参考: https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/3/README.html 8 | """ 9 | 10 | __author__ = '__L1n__w@tch' 11 | 12 | 13 | def no_argument_decorator(function): 14 | # 注意这是在脚本被解释期间(还没进入 main 代码就在跑的了) 15 | print("I am a 无参数修饰器") 16 | 17 | def wrapper(): 18 | print("{} 装饰开始 {}".format("*" * 30, "*" * 30)) 19 | function() 20 | print("{} 装饰结束 {}".format("*" * 30, "*" * 30)) 21 | 22 | return wrapper 23 | 24 | 25 | def decorator_maker_with_arguments(decorator_arg1, decorator_arg2): 26 | print("创建装饰器, 同时接收参数: {}, {}".format(decorator_arg1, decorator_arg2)) 27 | 28 | def my_decorator(func): 29 | print("装饰器, 得到参数: {}, {}".format(decorator_arg1, decorator_arg2)) 30 | 31 | # 不要忘了装饰器参数和函数参数! 32 | def wrapped(*args, **kwargs): 33 | print("装饰函数得到的参数: {}, {}, {}, {}".format(decorator_arg1, decorator_arg2, 34 | args, kwargs)) 35 | return func(*args, **kwargs) 36 | 37 | return wrapped 38 | 39 | return my_decorator 40 | 41 | 42 | @decorator_maker_with_arguments("a", "b") 43 | # @no_argument_decorator 44 | def no_argument_function(): 45 | print("I am a 普通的无参数函数") 46 | 47 | 48 | @decorator_maker_with_arguments("a", "b") 49 | # @no_argument_decorator 50 | def argument_function(*args): 51 | print("I am a 带多个参数的函数") 52 | 53 | 54 | @decorator_maker_with_arguments("a", "b") 55 | # @no_argument_decorator 56 | def args_kwargs_function(*args, **kwargs): 57 | print("I am a 带 args & kwargs 参数的函数") 58 | 59 | 60 | if __name__ == "__main__": 61 | no_argument_function() 62 | argument_function("c", "d") 63 | args_kwargs_function("c", "d") 64 | ``` -------------------------------------------------------------------------------- /Python 语言特性/7 单例模式.md: -------------------------------------------------------------------------------- 1 | # 文件 1 2 | singleton_for_import.py 3 | ```Python 4 | #!/bin/env python3 5 | # -*- coding: utf-8 -*- 6 | # version: Python3.X 7 | """ 作为被 import 的文件, 实现单例 8 | """ 9 | 10 | __author__ = '__L1n__w@tch' 11 | 12 | 13 | class MySingleton: 14 | def foo(self): 15 | pass 16 | 17 | 18 | my_singleton = MySingleton() 19 | 20 | if __name__ == "__main__": 21 | pass 22 | 23 | ``` 24 | 25 | # 文件 2 26 | singleton.py 27 | ```Python 28 | #!/bin/env python3 29 | # -*- coding: utf-8 -*- 30 | # version: Python3.X 31 | """ 单例模式的 4 种实现方法 32 | 33 | 1. 使用__new__方法 34 | 2. 共享属性(创建实例时把所有实例的 __dict__ 指向同一个字典,这样它们具有相同的属性和方法) 35 | 3. 装饰器版本 36 | 4. import方法 37 | """ 38 | from singleton_for_import import my_singleton 39 | 40 | __author__ = '__L1n__w@tch' 41 | 42 | 43 | # 使用 __new__ 方法 44 | class Singleton: 45 | def __new__(cls, *args, **kwargs): 46 | if not hasattr(cls, "_instance"): 47 | orig = super(Singleton, cls) 48 | cls._instance = orig.__new__(cls, *args, **kwargs) 49 | return cls._instance 50 | 51 | 52 | class TestSingleton1(Singleton): 53 | var = 1 54 | 55 | 56 | """ 57 | 共享属性的方法, 不知道为何出错了 58 | class Singleton2: 59 | _state = {} 60 | 61 | def __new__(cls, *args, **kwargs): 62 | ob = super(Singleton2, cls).__new__(cls, *args, **kwargs) 63 | ob.__dict__ = cls._state 64 | return ob 65 | 66 | 67 | class TestSingleton2(Singleton2): 68 | var = 2 69 | """ 70 | 71 | 72 | def singleton(cls, *args, **kwargs): 73 | instances = dict() 74 | 75 | def get_instance(): 76 | if cls not in instances: 77 | instances[cls] = cls(*args, **kwargs) 78 | return instances[cls] 79 | 80 | return get_instance 81 | 82 | 83 | @singleton 84 | class TestSingleton3: 85 | var = 3 86 | 87 | 88 | if __name__ == "__main__": 89 | ts1 = TestSingleton1() 90 | ts2 = TestSingleton1() 91 | assert ts1 == ts2 # 仅有一个实例 92 | 93 | # ts3 = TestSingleton2() 94 | # ts4 = TestSingleton2() 95 | # assert ts3 == ts4 96 | 97 | ts5 = TestSingleton3() 98 | ts6 = TestSingleton3() 99 | assert ts5 == ts6 100 | 101 | my_singleton.foo() # import 到的本身就是一个实例 102 | ``` -------------------------------------------------------------------------------- /Python 语言特性/8 Python 函数式编程.md: -------------------------------------------------------------------------------- 1 | # func_code 2 | ```Python 3 | #!/bin/env python3 4 | # -*- coding: utf-8 -*- 5 | # version: Python3.X 6 | """ 函数式编程相关知识 7 | 8 | 完整版参考资料: 9 | http://coolshell.cn/articles/10822.html 10 | 11 | Python 中函数式编程支持: 12 | filter 函数的功能相当于过滤器, 调用一个布尔函数 bool_func 来迭代遍历每个 seq 中的元素; 13 | 返回一个使 bool_seq 返回值为 true 的元素的序列 14 | 15 | map 函数是对一个序列的每个项依次执行函数 16 | 17 | reduce 函数是对一个序列的每个项迭代调用函数 18 | """ 19 | import functools 20 | 21 | __author__ = '__L1n__w@tch' 22 | 23 | 24 | def test_filter(): 25 | """ 26 | 测试 filter 函数的功能 27 | :return: 28 | """ 29 | wait_to_filter = [i for i in range(10)] 30 | after_filter = filter(lambda x: x > 5, wait_to_filter) 31 | print("测试 filter: {}".format(list(after_filter))) 32 | 33 | 34 | def test_map(): 35 | """ 36 | 测试 map 函数的功能 37 | :return: 38 | """ 39 | wait_to_map = [i for i in range(10)] 40 | after_map = map(lambda x: x * 2, wait_to_map) 41 | print("测试 map: {}".format(list(after_map))) 42 | 43 | 44 | def test_reduce(): 45 | """ 46 | 测试 reduce 函数的功能, 看 doc 说 3.4 版本的 reduce 好像有所不同 47 | :return: 48 | """ 49 | wait_to_reduce = [i for i in range(1, 4)] 50 | after_reduce = functools.reduce(lambda x, y: x * y, wait_to_reduce) 51 | print("测试 reduce: {}".format(after_reduce)) 52 | 53 | 54 | if __name__ == "__main__": 55 | test_filter() # 过滤得到大于 5 的值 56 | test_map() # 对一个序列每个项都乘以 2 57 | test_reduce() # 求 3 的阶乘 58 | 59 | ``` -------------------------------------------------------------------------------- /Python 语言特性/9 Python 里的拷贝.md: -------------------------------------------------------------------------------- 1 | # about_copy.py 2 | ```Python 3 | #!/bin/env python3 4 | # -*- coding: utf-8 -*- 5 | # version: Python3.X 6 | """ 关于 Python 的拷贝, 有引用/浅复制/深复制的区别, (引用和 copy(), deepcopy() 的区别) 7 | """ 8 | 9 | import copy 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | if __name__ == "__main__": 14 | List = [1, 2, 3, 4, ["a", "b"]] 15 | 16 | one_list = List # 赋值, 传对象的引用 17 | second_list = copy.copy(List) # 对象拷贝, 浅拷贝 18 | third_list = copy.deepcopy(List) # 对象拷贝,深拷贝 19 | 20 | List.append(5) # 修改对象 List 21 | List[4].append("c") 22 | 23 | print("List: {}".format(List)) 24 | print("one_list: {}".format(one_list)) 25 | print("second_list: {}".format(second_list)) 26 | print("third_list: {}".format(third_list)) 27 | ``` -------------------------------------------------------------------------------- /Python 语言特性/readme.md: -------------------------------------------------------------------------------- 1 | # Python 语言特性 2 | 这一个节里主要是练习 Python 语言特性的相关代码。 3 | ## 参考资料 4 | [interview_Python](https://github.com/taizilongxu/interview_Python#Python%E8%AF%AD%E8%A8%80%E7%89%B9%E6%80%A7) 5 | ## 清单 6 | 1. Python的函数参数传递 7 | 2. @staticmethod和@classmethod 8 | 3. 类变量和实例变量 9 | 4. Python中单下划线和双下划线 10 | 5. \*args and \*\*kwargs 11 | 6. 面向切面编程AOP和装饰器 12 | 7. 单例模式 13 | 8. Python 函数式编程 14 | 9. Python 里的拷贝 15 | 16 | ## 零散知识点 17 | 18 | ### 元类(metaclass) 19 | 20 | 这个非常的不常用, 但是像 ORM 这种复杂的结构还是会需要的, [详情](http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-Python) 21 | 22 | ### 自省 23 | 24 | 自省就是面向对象的语言所写的程序在运行时, 所能知道对象的类型. 25 | 26 | 简单一句就是运行时能够获得对象的类型. 27 | 28 | 比如 ``type(), dir(), getattr(), hasattr(), isinstance()``. 29 | 30 | ### 字典推导式 31 | 32 | 可能你见过列表推导时 \#, 却没有见过字典推导式, 在 2.7 中才加入的: 33 | ``d = {key: value for (key, value) in iterable}`` 34 | 35 | ### 字符串格式化: % 和 .format 36 | 37 | ``.format`` 在许多方面看起来更便利. 38 | 39 | 对于 % 最烦人的是它无法同时传递一个变量和元组. 你可能会想下面的代码不会有什么问题: 40 | 41 | ``"hi there %s" % name`` 42 | 但是, 如果 name 恰好是 (1,2,3), 它将会抛出一个 TypeError 异常. 43 | 44 | 为了保证它总是正确的, 你必须这样做: 45 | 46 | ``"hi there %s" % (name,) # 提供一个单元素的数组而不是一个参数`` 47 | 但是有点丑. 48 | 49 | ``.format`` 就没有这些问题.你给的第二个问题也是这样, ``.format``好看多了. 50 | 51 | 你为什么不用它? 52 | 53 | * 不知道它(在读这个之前) 54 | 55 | 56 | * 为了和 Python2.5 兼容(譬如 [logging 库建议使用 %](http://stackoverflow.com/questions/5082452/Python-string-formatting-vs-format)) 57 | 58 | ### 迭代器和生成器 59 | 60 | [参考](https://taizilongxu.gitbooks.io/stackoverflow-about-Python/content/1/README.html) 61 | 62 | ### 鸭子类型 63 | 64 | “当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” 65 | 我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。 66 | 比如在 Python 中,有很多 file-like 的东西,比如 StringIO, GzipFile, socket。它们有很多相同的方法,我们把它们当作文件使用。 67 | 又比如 ``list.extend()`` 方法中, 我们并不关心它的参数是不是 list, 只要它是可迭代的, 所以它的参数可以是 list/tuple/dict/字符串/生成器等. 68 | 鸭子类型在动态语言中经常使用,非常灵活,使得 Python 不像 java那样专门去弄一大堆的设计模式。 69 | 70 | ### Python 中重载 71 | 72 | 函数重载主要是为了解决两个问题: 73 | 74 | * 可变参数类型 75 | 76 | 77 | * 可变参数个数 78 | 79 | 另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。 80 | 好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,Python 如何处理?答案是根本不需要处理,因为 Python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 Python 中很可能是相同的代码,没有必要做成两个不同函数。 81 | 那么对于情况 2 ,函数功能相同,但参数个数不同,Python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。 82 | 好了,鉴于情况 1 跟 情况 2 都有了解决方案,Python 自然就不需要函数重载了。 83 | 84 | ### 新式类和旧式类 85 | 86 | [这篇文章](http://www.cnblogs.com/btchenguang/archive/2012/09/17/2689146.html)很好的介绍了新式类的特性 87 | 新式类很早在 2.2 就出现了,所以旧式类完全是兼容的问题, Python3 里的类全部都是新式类. 这里有一个 MRO 问题可以了解下(新式类是广度优先,旧式类是深度优先),里讲的也很多. 88 | 89 | ### \_\_new\_\_ 和 \_\_init\_\_ 的区别 90 | 91 | * \_\_new\_\_ 是一个静态方法, 而\_\_init\_\_ 是一个实例方法. 92 | 93 | 94 | * \_\_new\_\_ 方法会返回一个创建的实例, 而\_\_init\_\_ 什么都不返回. 95 | 96 | 97 | * 只有在 \_\_new\_\_ 返回一个 cls 的实例时后面的 \_\_init\_\_ 才能被调用. 98 | 99 | 100 | * 当创建一个新实例时调用 \_\_new\_\_, 初始化一个实例时用 \_\_init\_\_. 101 | 102 | PS: \_\_metaclass\_\_ 是创建类时起作用. 所以我们可以分别使用 \_\_metaclass\_\_, \_\_new\_\_ 和 \_\_init\_\_ 来分别在类创建,实例创建和实例初始化的时候做一些小手脚. 103 | 104 | ### Python 中的作用域 105 | 106 | Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。 107 | 当 Python 遇到一个变量的话他会按照这样的顺序进行搜索: 108 | ``本地作用域(Local)→ 当前作用域被嵌入的本地作用域(Enclosing locals)→ 全局/模块作用域(Global)→ 内置作用域(Built-in)` ` 109 | 110 | ### GIL 线程全局锁 111 | 112 | 线程全局锁(Global Interpreter Lock), 即 Python 为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程. 113 | 见 Python 最难的问题 114 | 解决办法就是多进程和下面的协程(协程也只是单 CPU,但是能减小切换代价提升性能). 115 | 116 | ### 协程 117 | 118 | 简单点说协程是进程和线程的升级版, 进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间, 而协程就是用户自己控制切换的时机, 不再需要陷入系统的内核态. 119 | Python 里最常见的 yield 就是协程的思想! 120 | 121 | ### 闭包 122 | 123 | 闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。 124 | 当一个内嵌函数引用其外部作作用域的变量,我们就会得到一个闭包. 总结一下,创建一个闭包必须满足以下几点: 125 | * 必须有一个内嵌函数 126 | 127 | * 内嵌函数必须引用外部函数中的变量 128 | 129 | * 外部函数的返回值必须是内嵌函数 130 | 131 | 感觉闭包还是有难度的,几句话是说不明白的,还是查查相关资料. 132 | 133 | 重点是函数运行后并不会被撤销, 就像 16 题的 instance 字典一样, 当函数运行完后, instance 并不被销毁,而是继续留在内存空间里. 134 | 135 | 这个功能类似类里的类变量, 只不过迁移到了函数上. 136 | 137 | 闭包就像个空心球一样, 你知道外面和里面, 但你不知道中间是什么样. 138 | 139 | ### lambda 函数 140 | 其实就是一个匿名函数,为什么叫 lambda?因为和后面的函数式编程有关. 141 | 142 | ### Python 垃圾回收机制 143 | Python GC 主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。 144 | * 引用计数 145 | * PyObject 是每个对象必有的内容,其中 ob_refcnt 就是做为引用计数。当一个对象有新的引用时,它的 ob_refcnt 就会增加,当引用它的对象被删除,它的 ob_refcnt 就会减少.引用计数为 0 时,该对象生命就结束了。 146 | * 优点: 147 | * 简单 148 | * 实时性 149 | * 缺点: 150 | * 维护引用计数消耗资源 151 | * 循环引用 152 | * 标记-清除机制 153 | * 基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。 154 | * 分代技术 155 | * 分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。 156 | * Python 默认定义了三代对象集合,索引数越大,对象存活时间越长。 157 | * 举例: 当某些内存块 M 经过了 3 次垃圾收集的清洗之后还存活时,我们就将内存块 M 划到一个集合 A 中去,而新分配的内存都划分到集合 B 中去。当垃圾收集开始工作时,大多数情况都只对集合 B 进行垃圾回收,而对集合 A 进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合 B 中的某些内存块由于存活时间长而会被转移到集合 A 中,当然,集合 A 中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。 158 | 159 | ### Python 的 List 160 | 161 | [推荐](http://www.jianshu.com/p/J4U6rR) 162 | 163 | ### Python 的 is 164 | 165 | is 是对比地址,== 是对比值 166 | 167 | ### read, readline 和 readlines 168 | 169 | * read 读取整个文件 170 | * readline 读取下一行,使用生成器方法 171 | * readlines 读取整个文件到一个迭代器以供我们遍历 172 | 173 | ### Python 2 和 3 的区别 174 | 175 | [Python 2.7.x 与 Python 3.x 的主要差异](http://chenqx.github.io/2014/11/10/Key-differences-between-Python-2-7-x-and-Python-3-x/) -------------------------------------------------------------------------------- /Python 面试编程题/1 台阶问题 斐波那契/fibonacci.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 又见斐波那契数列 5 | 6 | 这回是练习了经典的面试题: 7 | 一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级. 求该青蛙跳上一个 n 级的台阶总共有多少种跳法? 8 | 9 | 斐波那契除了 GitHub 面试题给的那三种外, 还有我之前实现过的一种, 都整理在这个文件了 10 | """ 11 | import timeit 12 | from functools import wraps 13 | 14 | __author__ = '__L1n__w@tch' 15 | 16 | 17 | def recursion(n): 18 | """ 19 | 普通的递归求斐波那契 20 | :param n: 21 | :return: 22 | """ 23 | if n <= 2: 24 | return n 25 | else: 26 | return recursion(n - 1) + recursion(n - 2) 27 | 28 | 29 | def memory(function): 30 | """ 31 | 作为修饰器存在的 32 | :param function: 33 | :return: 34 | """ 35 | cache = {} 36 | 37 | @wraps(function) # 加这句主要是为了保留被修饰的函数的名字 38 | def wrap(args): 39 | if args not in cache: 40 | cache[args] = function(args) 41 | return cache[args] 42 | 43 | return wrap 44 | 45 | 46 | @memory 47 | def memory_recursion(n): 48 | """ 49 | 函数本身依旧是普通的递归求斐波那契, 但是装有修饰器 50 | :param n: 51 | :return: 52 | """ 53 | if n <= 2: 54 | return n 55 | else: 56 | return memory_recursion(n - 1) + memory_recursion(n - 2) 57 | 58 | 59 | def circle(n): 60 | """ 61 | 循环求斐波那契 62 | :param n: 63 | :return: 64 | """ 65 | a, b = 0, 1 66 | for i in range(n): 67 | a, b = b, a + b 68 | return b 69 | 70 | 71 | class Fibonacci: 72 | """ 73 | 自己之前写的一个斐波那契数列 74 | """ 75 | 76 | def __init__(self, f0, f1): 77 | self.f0 = f0 78 | self.f1 = f1 79 | 80 | def _fib(self, a, b): 81 | a = self.f0 82 | b = self.f1 83 | yield a 84 | yield b 85 | while True: 86 | a, b = b, a + b 87 | yield b 88 | 89 | def fib_generator(self): 90 | """ 91 | 生成器 92 | :return: 93 | """ 94 | return self._fib(self.f0, self.f1) 95 | 96 | 97 | if __name__ == "__main__": 98 | print("方法一: 匿名函数(其实就是递归), 注意这种写法被 PEP8 报警了...") 99 | # fibonacci_1 = lambda n: n if n <= 2 else fibonacci_1(n - 1) + fibonacci_1(n - 2) 100 | fibonacci_1 = recursion 101 | time_cost = timeit.timeit("recursion(33)", setup="from fibonacci import recursion", number=1) 102 | print("fibonacci_1(33) 耗时: {}".format(time_cost)) 103 | 104 | print("方法二: 依旧递归求解, 不过加了个记忆用的修饰器, 速率翻倍了都") 105 | fibonacci_2 = memory_recursion 106 | time_cost = timeit.timeit("memory_recursion(33)", setup="from fibonacci import memory_recursion") 107 | print("fibonacci_2(33) 耗时: {}".format(time_cost)) 108 | 109 | print("方法三: 循环求解") 110 | fibonacci_3 = circle 111 | time_cost = timeit.timeit("circle(33)", setup="from fibonacci import circle", number=1) 112 | print("fibonacci_3(33) 耗时: {}".format(time_cost)) 113 | 114 | print("方法四: 同样循环求解, 不过是通过生成器实现的") 115 | fibonacci_4 = Fibonacci(1, 2).fib_generator() 116 | -------------------------------------------------------------------------------- /Python 面试编程题/1 台阶问题 斐波那契/unittest_fibonacci.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 需要练习一下单元测试的相关知识 5 | 6 | 本文件是对同文件夹下的 fibonacci 几种写法进行测试 7 | """ 8 | import unittest 9 | from fibonacci import recursion, memory_recursion, circle 10 | 11 | 12 | __author__ = '__L1n__w@tch' 13 | 14 | 15 | class FibonacciTest(unittest.TestCase): 16 | def setUp(self): 17 | self.wait_to_test = [recursion, memory_recursion, circle] # 待测试的函数 18 | 19 | def normal_test(self): 20 | """ 21 | 简单的功能性测试罢了 22 | :return: 23 | """ 24 | for function in self.wait_to_test: 25 | self.failUnless(function(1) == 1) 26 | self.failUnless(function(2) == 2) 27 | self.failUnless(function(3) == 3) 28 | self.failUnless(function(4) == 5) 29 | self.failUnless(function(5) == 8) 30 | self.failUnless(function(6) == 13) 31 | self.failUnless(function(7) == 21) 32 | self.failUnless(function(13) == 377) 33 | self.failUnless(function(15) == 987) 34 | self.failUnless(function(20) == 10946) 35 | self.failUnless(function(25) == 121393) 36 | self.failUnless(function(29) == 832040) 37 | self.failUnless(function(33) == 5702887) 38 | if function.__name__ == "recursion": 39 | print("递归 50 次时间太长, 不测试了") 40 | continue 41 | self.failUnless(function(50) == 20365011074) 42 | print("函数: {}, 测试完毕".format(function.__name__)) 43 | 44 | 45 | if __name__ == "__main__": 46 | unittest.main() 47 | -------------------------------------------------------------------------------- /Python 面试编程题/1 台阶问题 斐波那契/斐波那契.md: -------------------------------------------------------------------------------- 1 | # 题目说明 2 | 经典的面试题: 3 | 4 | 一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级. 求该青蛙跳上一个 n 级的台阶总共有多少种跳法? 5 | 6 | 斐波那契除了 GitHub 面试题给的那三种外, 还有我之前实现过的一种, 都整理在这个文件了, 包括: 7 | * 递归求斐波那契(函数形式) 8 | * 循环求斐波那契(函数形式) 9 | * 带记忆的递归求斐波那契(函数形式 + 装饰器) 10 | * 循环求斐波那契(类形式) 11 | 12 | # fibonacci.py 13 | ```Python 14 | #!/bin/env python3 15 | # -*- coding: utf-8 -*- 16 | # version: Python3.X 17 | 18 | import timeit 19 | from functools import wraps 20 | 21 | __author__ = '__L1n__w@tch' 22 | 23 | 24 | def recursion(n): 25 | """ 26 | 普通的递归求斐波那契 27 | :param n: 28 | :return: 29 | """ 30 | if n <= 2: 31 | return n 32 | else: 33 | return recursion(n - 1) + recursion(n - 2) 34 | 35 | 36 | def memory(function): 37 | """ 38 | 作为修饰器存在的 39 | :param function: 40 | :return: 41 | """ 42 | cache = {} 43 | 44 | @wraps(function) # 加这句主要是为了保留被修饰的函数的名字 45 | def wrap(args): 46 | if args not in cache: 47 | cache[args] = function(args) 48 | return cache[args] 49 | 50 | return wrap 51 | 52 | 53 | @memory 54 | def memory_recursion(n): 55 | """ 56 | 函数本身依旧是普通的递归求斐波那契, 但是装有修饰器 57 | :param n: 58 | :return: 59 | """ 60 | if n <= 2: 61 | return n 62 | else: 63 | return memory_recursion(n - 1) + memory_recursion(n - 2) 64 | 65 | 66 | def circle(n): 67 | """ 68 | 循环求斐波那契 69 | :param n: 70 | :return: 71 | """ 72 | a, b = 0, 1 73 | for i in range(n): 74 | a, b = b, a + b 75 | return b 76 | 77 | 78 | class Fibonacci: 79 | """ 80 | 自己之前写的一个斐波那契数列 81 | """ 82 | 83 | def __init__(self, f0, f1): 84 | self.f0 = f0 85 | self.f1 = f1 86 | 87 | def _fib(self, a, b): 88 | a = self.f0 89 | b = self.f1 90 | yield a 91 | yield b 92 | while True: 93 | a, b = b, a + b 94 | yield b 95 | 96 | def fib_generator(self): 97 | """ 98 | 生成器 99 | :return: 100 | """ 101 | return self._fib(self.f0, self.f1) 102 | 103 | 104 | if __name__ == "__main__": 105 | print("方法一: 匿名函数(其实就是递归), 注意这种写法被 PEP8 报警了...") 106 | # fibonacci_1 = lambda n: n if n <= 2 else fibonacci_1(n - 1) + fibonacci_1(n - 2) 107 | fibonacci_1 = recursion 108 | time_cost = timeit.timeit("recursion(33)", setup="from fibonacci import recursion", number=1) 109 | print("fibonacci_1(33) 耗时: {}".format(time_cost)) 110 | 111 | print("方法二: 依旧递归求解, 不过加了个记忆用的修饰器, 速率翻倍了都") 112 | fibonacci_2 = memory_recursion 113 | time_cost = timeit.timeit("memory_recursion(33)", setup="from fibonacci import memory_recursion") 114 | print("fibonacci_2(33) 耗时: {}".format(time_cost)) 115 | 116 | print("方法三: 循环求解") 117 | fibonacci_3 = circle 118 | time_cost = timeit.timeit("circle(33)", setup="from fibonacci import circle", number=1) 119 | print("fibonacci_3(33) 耗时: {}".format(time_cost)) 120 | 121 | print("方法四: 同样循环求解, 不过是通过生成器实现的") 122 | fibonacci_4 = Fibonacci(1, 2).fib_generator() 123 | ``` 124 | 125 | # 单元测试 126 | 本文件是对同文件夹下的 fibonacci 几种写法进行测试 127 | ```Python 128 | #!/bin/env python3 129 | # -*- coding: utf-8 -*- 130 | # version: Python3.X 131 | 132 | import unittest 133 | from fibonacci import recursion, memory_recursion, circle 134 | 135 | 136 | __author__ = '__L1n__w@tch' 137 | 138 | 139 | class FibonacciTest(unittest.TestCase): 140 | def setUp(self): 141 | self.wait_to_test = [recursion, memory_recursion, circle] # 待测试的函数 142 | 143 | def normal_test(self): 144 | """ 145 | 简单的功能性测试罢了 146 | :return: 147 | """ 148 | for function in self.wait_to_test: 149 | self.failUnless(function(1) == 1) 150 | self.failUnless(function(2) == 2) 151 | self.failUnless(function(3) == 3) 152 | self.failUnless(function(4) == 5) 153 | self.failUnless(function(5) == 8) 154 | self.failUnless(function(6) == 13) 155 | self.failUnless(function(7) == 21) 156 | self.failUnless(function(13) == 377) 157 | self.failUnless(function(15) == 987) 158 | self.failUnless(function(20) == 10946) 159 | self.failUnless(function(25) == 121393) 160 | self.failUnless(function(29) == 832040) 161 | self.failUnless(function(33) == 5702887) 162 | if function.__name__ == "recursion": 163 | print("递归 50 次时间太长, 不测试了") 164 | continue 165 | self.failUnless(function(50) == 20365011074) 166 | print("函数: {}, 测试完毕".format(function.__name__)) 167 | 168 | 169 | if __name__ == "__main__": 170 | unittest.main() 171 | ``` -------------------------------------------------------------------------------- /Python 面试编程题/10 快排/qsort.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 快排的 Python 实现 5 | """ 6 | 7 | __author__ = '__L1n__w@tch' 8 | 9 | 10 | def qsort(a_list): 11 | if len(a_list) == 0: 12 | return a_list 13 | else: 14 | pivot = a_list[0] 15 | small = qsort([x for x in a_list[1:] if x < pivot]) 16 | big = qsort([x for x in a_list[1:] if x >= pivot]) 17 | return small + [pivot] + big 18 | 19 | 20 | if __name__ == "__main__": 21 | List = [1, 3, 5, 1, 2] 22 | print(qsort(List)) 23 | -------------------------------------------------------------------------------- /Python 面试编程题/10 快排/unittest_sort.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 单元测试快排 5 | """ 6 | import random 7 | import unittest 8 | from qsort import qsort 9 | 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | class TestQSort(unittest.TestCase): 15 | def test_qsort(self): 16 | for i in range(30): 17 | list_wait_to_sort = [random.randint(-1000, 1000) for i in range(100)] 18 | self.failUnless(sorted(list_wait_to_sort) == qsort(list_wait_to_sort)) 19 | -------------------------------------------------------------------------------- /Python 面试编程题/10 快排/快排.md: -------------------------------------------------------------------------------- 1 | # 题目 2 | 快排实现 3 | 4 | # qsort.py 5 | ```Python 6 | #!/bin/env python3 7 | # -*- coding: utf-8 -*- 8 | # version: Python3.X 9 | 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | def qsort(a_list): 15 | if len(a_list) == 0: 16 | return a_list 17 | else: 18 | pivot = a_list[0] 19 | small = qsort([x for x in a_list[1:] if x < pivot]) 20 | big = qsort([x for x in a_list[1:] if x >= pivot]) 21 | return small + [pivot] + big 22 | 23 | 24 | if __name__ == "__main__": 25 | List = [1, 3, 5, 1, 2] 26 | print(qsort(List)) 27 | ``` 28 | 29 | # 单元测试 30 | ```Python 31 | #!/bin/env python3 32 | # -*- coding: utf-8 -*- 33 | # version: Python3.X 34 | """ 单元测试快排 35 | """ 36 | import random 37 | import unittest 38 | from qsort import qsort 39 | 40 | 41 | __author__ = '__L1n__w@tch' 42 | 43 | 44 | class TestQSort(unittest.TestCase): 45 | def test_qsort(self): 46 | for i in range(30): 47 | list_wait_to_sort = [random.randint(-1000, 1000) for i in range(100)] 48 | self.failUnless(sorted(list_wait_to_sort) == qsort(list_wait_to_sort)) 49 | ``` -------------------------------------------------------------------------------- /Python 面试编程题/11 找零问题/coin_change.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 找零问题, 为啥看答案有点像背包问题... 5 | """ 6 | 7 | __author__ = '__L1n__w@tch' 8 | 9 | 10 | def coin_change(values, money): 11 | """ 12 | 背包问题解法? 13 | :param values: [25, 21, 10, 5, 1] 14 | :param money: 63 15 | :return: {1:1, 2:2, 3:3, 4:4, 5:1, ..., 63:3} 16 | """ 17 | coin_count = {i: 0 for i in range(money_wait_to_change + 1)} 18 | 19 | for cents in range(1, money + 1): 20 | min_coins = cents # 从第一个开始到money的所有情况初始 21 | for value in values: 22 | if value <= cents: 23 | temp = coin_count[cents - value] + 1 # 这不是经典的背包? 24 | if temp < min_coins: 25 | min_coins = temp 26 | coin_count[cents] = min_coins 27 | print('面值为:{0} 的最小硬币数目为:{1} '.format(cents, coin_count[cents])) 28 | 29 | 30 | if __name__ == '__main__': 31 | pocket_monkey = [25, 21, 10, 5, 1] 32 | money_wait_to_change = 63 33 | coin_change(pocket_monkey, money_wait_to_change) 34 | -------------------------------------------------------------------------------- /Python 面试编程题/11 找零问题/找零问题.md: -------------------------------------------------------------------------------- 1 | # 题目 2 | 找零问题, 给个金额让你找出对应的最小硬币数目 3 | 4 | # coin_change.py 5 | ```Python 6 | #!/bin/env python3 7 | # -*- coding: utf-8 -*- 8 | # version: Python3.X 9 | 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | def coin_change(values, money): 15 | """ 16 | 背包问题解法? 17 | :param values: [25, 21, 10, 5, 1] 18 | :param money: 63 19 | :return: {1:1, 2:2, 3:3, 4:4, 5:1, ..., 63:3} 20 | """ 21 | coin_count = {i: 0 for i in range(money_wait_to_change + 1)} 22 | 23 | for cents in range(1, money + 1): 24 | min_coins = cents # 从第一个开始到money的所有情况初始 25 | for value in values: 26 | if value <= cents: 27 | temp = coin_count[cents - value] + 1 # 这不是经典的背包? 28 | if temp < min_coins: 29 | min_coins = temp 30 | coin_count[cents] = min_coins 31 | print('面值为:{0} 的最小硬币数目为:{1} '.format(cents, coin_count[cents])) 32 | 33 | 34 | if __name__ == '__main__': 35 | pocket_monkey = [25, 21, 10, 5, 1] 36 | money_wait_to_change = 63 37 | coin_change(pocket_monkey, money_wait_to_change) 38 | ``` 39 | -------------------------------------------------------------------------------- /Python 面试编程题/13 单链表逆置/single_list_reverse.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 对单链表实现逆置操作, 即 1 -> 2 -> 3 变为 3 -> 2 -> 1 5 | """ 6 | 7 | __author__ = '__L1n__w@tch' 8 | 9 | 10 | class ListNode: 11 | def __init__(self, data=None, next_node=None): 12 | self.data = data 13 | self.next_node = next_node 14 | 15 | 16 | def print_single_list(head_node): 17 | """ 18 | 打印单链表 19 | :param head_node: ListNode() 20 | :return: None 21 | """ 22 | if head_node: 23 | print(head_node.data, end=" -> ") 24 | next_node = head_node.next_node 25 | while next_node: 26 | print(next_node.data, end=" -> ") 27 | next_node = next_node.next_node 28 | print("None") 29 | 30 | 31 | def reverse_single_list(head_node): 32 | """ 33 | GitHub 上的思路是用 3 个指针, 自己的思路是用栈来解决, 看起来 GitHub 思路简单些 34 | :param head_node: ListNode() 35 | :return: None 36 | """ 37 | pre = head_node 38 | current = head_node.next_node 39 | pre.next_node = None 40 | 41 | while current: 42 | temp = current.next_node 43 | current.next_node = pre 44 | pre = current 45 | current = temp 46 | return pre 47 | 48 | 49 | if __name__ == "__main__": 50 | single_list = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5, ListNode(6, ListNode(7, ListNode(8)))))))) 51 | print_single_list(single_list) 52 | 53 | reversed_single_list = reverse_single_list(single_list) 54 | print_single_list(reversed_single_list) 55 | -------------------------------------------------------------------------------- /Python 面试编程题/13 单链表逆置/单链表逆置.md: -------------------------------------------------------------------------------- 1 | # 题目 2 | 对单链表实现逆置操作, 即 `1 -> 2 -> 3` 变为 `3 -> 2 -> 1` 3 | 4 | # single_list_reverse.py 5 | ```python 6 | #!/bin/env python3 7 | # -*- coding: utf-8 -*- 8 | # version: Python3.X 9 | 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | class ListNode: 15 | def __init__(self, data=None, next_node=None): 16 | self.data = data 17 | self.next_node = next_node 18 | 19 | 20 | def print_single_list(head_node): 21 | """ 22 | 打印单链表 23 | :param head_node: ListNode() 24 | :return: None 25 | """ 26 | if head_node: 27 | print(head_node.data, end=" -> ") 28 | next_node = head_node.next_node 29 | while next_node: 30 | print(next_node.data, end=" -> ") 31 | next_node = next_node.next_node 32 | print("None") 33 | 34 | 35 | def reverse_single_list(head_node): 36 | """ 37 | GitHub 上的思路是用 3 个指针, 自己的思路是用栈来解决, 看起来 GitHub 思路简单些 38 | :param head_node: ListNode() 39 | :return: None 40 | """ 41 | pre = head_node 42 | current = head_node.next_node 43 | pre.next_node = None 44 | 45 | while current: 46 | temp = current.next_node 47 | current.next_node = pre 48 | pre = current 49 | current = temp 50 | return pre 51 | 52 | 53 | if __name__ == "__main__": 54 | single_list = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5, ListNode(6, ListNode(7, ListNode(8)))))))) 55 | print_single_list(single_list) 56 | 57 | reversed_single_list = reverse_single_list(single_list) 58 | print_single_list(reversed_single_list) 59 | ``` -------------------------------------------------------------------------------- /Python 面试编程题/2 变态台阶问题/similar_frog_jump.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 变态台阶问题, 一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级, 它也可以跳上 n 级. 求该青蛙跳上一个 n 级的台阶总共有多少种跳法 5 | 6 | 根据数学归纳法可证得答案为 2 ^ n - 1 (可参考剑指 Offer 面试题 9) 7 | """ 8 | 9 | __author__ = '__L1n__w@tch' 10 | 11 | 12 | def recursion(steps): 13 | if steps < 2: 14 | return steps 15 | else: 16 | return 2 * recursion(steps - 1) 17 | 18 | 19 | if __name__ == "__main__": 20 | n = 233 21 | print("{} 级台阶: {}".format(n, recursion(n))) 22 | 23 | compute_jump = lambda steps: steps if steps < 2 else 2 * compute_jump(steps - 1) 24 | print("{} 级台阶: {}".format(n, compute_jump(n))) 25 | -------------------------------------------------------------------------------- /Python 面试编程题/2 变态台阶问题/变态台阶问题.md: -------------------------------------------------------------------------------- 1 | # 题目说明 2 | 变态台阶问题, 一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级, 它也可以跳上 n 级. 求该青蛙跳上一个 n 级的台阶总共有多少种跳法? 3 | 4 | 根据数学归纳法可证得答案为 `2 ^ (n - 1)` (可参考剑指 Offer 面试题 9) 5 | 6 | # similar_frog_jump.py 7 | ```Python 8 | #!/bin/env python3 9 | # -*- coding: utf-8 -*- 10 | # version: Python3.X 11 | 12 | __author__ = '__L1n__w@tch' 13 | 14 | 15 | def recursion(steps): 16 | if steps < 2: 17 | return steps 18 | else: 19 | return 2 * recursion(steps - 1) 20 | 21 | 22 | if __name__ == "__main__": 23 | n = 233 24 | print("{} 级台阶: {}".format(n, recursion(n))) 25 | 26 | compute_jump = lambda steps: steps if steps < 2 else 2 * compute_jump(steps - 1) 27 | print("{} 级台阶: {}".format(n, compute_jump(n))) 28 | ``` -------------------------------------------------------------------------------- /Python 面试编程题/3 矩形覆盖/rectangle.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 矩形覆盖 5 | 6 | 同样可以参考剑指 Offer (面试题 9) 7 | 8 | 解题思路摘要: 9 | 可以用 2 * 1 的小矩形横着或者竖着去覆盖更大的矩形。请问用 8 个 2 * 1 的小矩形无重叠地覆盖一个 2 * 8 的大矩形,总共有多少种方法? 10 | 11 | 我们先把 2 * 8 的覆盖方法记为 f(8)。用第一个 1 * 2 小矩形去覆盖大矩形的最左边时有两个选择,竖着放或者横着放。 12 | 当竖着放的时候,右边还剩下2 * 7 的区域,这种情况下的覆盖方法记为 f(7)。 13 | 14 | 接下来考虑横着放的情况。当 1 * 2 的小矩形横着放在左上角的时候,右下角必须和横着放一个 1 * 2 的小矩形,而在右边还剩下 2 * 6 的区域, 15 | 这种情形下的覆盖方法记为 f(6),因此 f(8) = f(7) + f(6)。此时可以看出,这仍然是斐波那契数列。 16 | """ 17 | 18 | __author__ = '__L1n__w@tch' 19 | 20 | 21 | def circle_fibonacci(steps, fn_1, fn_2): 22 | """ 23 | 循环求解斐波那契数列, f(n) = f(n - 1) + f(n - 2) 24 | :param steps: 阶数 25 | :param fn_1: f(n - 1) 26 | :param fn_2: f(n - 2) 27 | :return: f(n) 28 | """ 29 | for i in range(steps): 30 | fn_1, fn_2 = fn_2, fn_1 + fn_2 31 | return fn_2 32 | 33 | 34 | if __name__ == "__main__": 35 | n = 3 36 | 37 | print("{} 级台阶: {}".format(n, circle_fibonacci(n, 0, 1))) 38 | -------------------------------------------------------------------------------- /Python 面试编程题/3 矩形覆盖/矩阵覆盖.md: -------------------------------------------------------------------------------- 1 | # 题目说明 2 | 3 | 矩形覆盖 4 | 5 | 可以用 2 \* 1 的小矩形横着或者竖着去覆盖更大的矩形。请问用 8 个 2 \* 1 的小矩形无重叠地覆盖一个 2 \* 8 的大矩形,总共有多少种方法? 6 | 7 | 同样可以参考剑指 Offer \(面试题 9\) 8 | 9 | 解题思路摘要: 10 | 11 | ``` 12 | 我们先把 2 * 8 的覆盖方法记为 f(8)。用第一个 1 * 2 小矩形去覆盖大矩形的最左边时有两个选择,竖着放或者横着放。 13 | 14 | 当竖着放的时候,右边还剩下2 * 7 的区域,这种情况下的覆盖方法记为 f(7)。 15 | 16 | 接下来考虑横着放的情况。当 1 * 2 的小矩形横着放在左上角的时候,右下角必须和横着放一个 1 * 2 的小矩形,而在右边还剩下 2 * 6 的区域。 17 | 18 | 这种情形下的覆盖方法记为 f(6),因此 f(8) = f(7) + f(6)。此时可以看出,这仍然是斐波那契数列。 19 | ``` 20 | 21 | # rectangle.py 22 | 23 | ```python 24 | #!/bin/env python3 25 | # -*- coding: utf-8 -*- 26 | # version: Python3.X 27 | 28 | __author__ = '__L1n__w@tch' 29 | 30 | 31 | def circle_fibonacci(steps, fn_1, fn_2): 32 | """ 33 | 循环求解斐波那契数列, f(n) = f(n - 1) + f(n - 2) 34 | :param steps: 阶数 35 | :param fn_1: f(n - 1) 36 | :param fn_2: f(n - 2) 37 | :return: f(n) 38 | """ 39 | for i in range(steps): 40 | fn_1, fn_2 = fn_2, fn_1 + fn_2 41 | return fn_2 42 | 43 | 44 | if __name__ == "__main__": 45 | n = 3 46 | 47 | print("{} 级台阶: {}".format(n, circle_fibonacci(n, 0, 1))) 48 | ``` 49 | 50 | -------------------------------------------------------------------------------- /Python 面试编程题/4 杨氏矩阵查找/rectangle_search.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ GitHub 上只给了题目没给源代码, 是嫌太简单了吗... 5 | 6 | 题目描述: 7 | 在一个 m 行 n 列二维数组中, 每一行都按照从左到右递增的顺序排序, 每一列都按照从上到下递增的顺序排序. 8 | 请完成一个函数, 输入这样的一个二维数组和一个整数, 判断数组中是否含有该整数 9 | 10 | 解答思路: 11 | 参考: 剑指 Offer (面试题 3) 12 | 总结查找的过程,发现规律如下: 13 | 首先选取数组中右上角的数字。如果该数字等于要查找的数字,查找过程结束; 14 | 如果该数字大于要查找的数字,剔除这个数字所在的列; 15 | 如果该数字小于要查找的数字,剔除这个数字所在的行。 16 | 也就是说如果要查找的数字不在数组的右上角,则每一次都在数组的查找范围中剔除一行或者一列,这样每一步都可以缩小查找的范围, 17 | 直到找到要查找的数字,或者查找范围为空。 18 | """ 19 | import timeit 20 | import random 21 | 22 | __author__ = '__L1n__w@tch' 23 | 24 | 25 | def python_style_solve(a_list, number_to_find): 26 | """ 27 | 用 Python 的风格解决, 思路是把二维数组转换为一维数组, 然后执行查找 28 | :param a_list: 要查找的二维数组 29 | :param number_to_find: 待查找的数字 30 | :return: True or False 31 | """ 32 | sum_list = list() 33 | for each in a_list: 34 | sum_list.extend(each) 35 | if number_to_find in sum_list: 36 | return True 37 | # print("Found!") 38 | 39 | 40 | def c_style_solve(a_list, rows, columns, number_to_find): 41 | """ 42 | 用 C 的风格解决, 思路参考剑指 Offer 43 | :param a_list: 要查找的二维数组 44 | :param rows: 行 45 | :param columns: 列 46 | :param number_to_find: 待查找的数字 47 | :return: True or False 48 | """ 49 | found = False 50 | 51 | if a_list is not None and rows > 0 and columns > 0: 52 | row, column = 0, columns - 1 53 | while row < rows and column >= 0: 54 | if a_list[row][column] == number_to_find: 55 | found = True 56 | break 57 | elif a_list[row][column] > number_to_find: 58 | column -= 1 59 | else: 60 | row += 1 61 | return found 62 | 63 | 64 | if __name__ == "__main__": 65 | python_time = list() 66 | c_time = list() 67 | 68 | for i in range(30): 69 | number = random.choice([i for i in range(9)]) 70 | print("第 {} 次, 查找数字: {}".format(i + 1, number)) 71 | 72 | test_list = [[i for i in range(3)], [i for i in range(3, 6)], [i for i in range(6, 9)]] 73 | time_cost = timeit.timeit("python_style_solve(test_list, {})".format(number), 74 | setup="from __main__ import python_style_solve, test_list") 75 | print("Python 风格执行时间: {} s".format(time_cost)) 76 | python_time.append(time_cost) 77 | 78 | time_cost = timeit.timeit("c_style_solve(test_list, len(test_list), len(test_list[0]), {})".format(number), 79 | setup="from __main__ import c_style_solve, test_list") 80 | print("C 风格执行时间: {} s".format(time_cost)) 81 | c_time.append(time_cost) 82 | 83 | print("Python 平均时间: {}, C 平均时间: {}".format(sum(python_time) / len(python_time), sum(c_time) / len(c_time))) 84 | -------------------------------------------------------------------------------- /Python 面试编程题/4 杨氏矩阵查找/unittest_rectangle_search.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 对杨氏矩阵查找的几种解法进行单元测试 5 | """ 6 | import unittest 7 | from rectangle_search import python_style_solve, c_style_solve 8 | 9 | __author__ = '__L1n__w@tch' 10 | 11 | 12 | class TestAnswer(unittest.TestCase): 13 | def setUp(self): 14 | self.repeat_list = [[1, 2, 8, 9], [2, 4, 9, 12], [4, 7, 10, 13], [6, 8, 11, 15]] 15 | self.no_repeat_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]] 16 | 17 | def test_normal(self): 18 | # 测试数字在其中的情况 19 | wait_to_search = [1, 9, 2, 12, 4, 13, 6, 15, 11, 8, 10, 7, 9, 4, 8, 2] 20 | print("二维数组: ".format(self.repeat_list)) 21 | for each_number in wait_to_search: 22 | print("测试查找数字: {}".format(each_number)) 23 | self.failUnless(python_style_solve(self.repeat_list, each_number)) 24 | self.failUnless( 25 | c_style_solve(self.repeat_list, len(self.repeat_list), len(self.repeat_list[0]), each_number)) 26 | 27 | # 测试数字不在其中的情况 28 | # self.failIf() 29 | 30 | 31 | if __name__ == "__main__": 32 | pass 33 | -------------------------------------------------------------------------------- /Python 面试编程题/4 杨氏矩阵查找/杨氏矩阵查找.md: -------------------------------------------------------------------------------- 1 | # 题目 2 | 在一个 m 行 n 列二维数组中, 每一行都按照从左到右递增的顺序排序, 每一列都按照从上到下递增的顺序排序.请完成一个函数, 输入这样的一个二维数组和一个整数, 判断数组中是否含有该整数 3 | 4 | # 思路 5 | * 参考: 剑指 Offer (面试题 3) 6 | * 总结查找的过程,发现规律如下: 7 | * 首先选取数组中右上角的数字。如果该数字等于要查找的数字,查找过程结束; 8 | * 如果该数字大于要查找的数字,剔除这个数字所在的列; 9 | * 如果该数字小于要查找的数字,剔除这个数字所在的行。 10 | * 也就是说如果要查找的数字不在数组的右上角,则每一次都在数组的查找范围中剔除一行或者一列,这样每一步都可以缩小查找的范围, 11 | * 直到找到要查找的数字,或者查找范围为空。 12 | 13 | # rectangle_search.py 14 | ```Python 15 | #!/bin/env python3 16 | # -*- coding: utf-8 -*- 17 | # version: Python3.X 18 | 19 | import timeit 20 | import random 21 | 22 | __author__ = '__L1n__w@tch' 23 | 24 | 25 | def python_style_solve(a_list, number_to_find): 26 | """ 27 | 用 Python 的风格解决, 思路是把二维数组转换为一维数组, 然后执行查找 28 | :param a_list: 要查找的二维数组 29 | :param number_to_find: 待查找的数字 30 | :return: True or False 31 | """ 32 | sum_list = list() 33 | for each in a_list: 34 | sum_list.extend(each) 35 | if number_to_find in sum_list: 36 | return True 37 | # print("Found!") 38 | 39 | 40 | def c_style_solve(a_list, rows, columns, number_to_find): 41 | """ 42 | 用 C 的风格解决, 思路参考剑指 Offer 43 | :param a_list: 要查找的二维数组 44 | :param rows: 行 45 | :param columns: 列 46 | :param number_to_find: 待查找的数字 47 | :return: True or False 48 | """ 49 | found = False 50 | 51 | if a_list is not None and rows > 0 and columns > 0: 52 | row, column = 0, columns - 1 53 | while row < rows and column >= 0: 54 | if a_list[row][column] == number_to_find: 55 | found = True 56 | break 57 | elif a_list[row][column] > number_to_find: 58 | column -= 1 59 | else: 60 | row += 1 61 | return found 62 | 63 | 64 | if __name__ == "__main__": 65 | python_time = list() 66 | c_time = list() 67 | 68 | for i in range(30): 69 | number = random.choice([i for i in range(9)]) 70 | print("第 {} 次, 查找数字: {}".format(i + 1, number)) 71 | 72 | test_list = [[i for i in range(3)], [i for i in range(3, 6)], [i for i in range(6, 9)]] 73 | time_cost = timeit.timeit("python_style_solve(test_list, {})".format(number), 74 | setup="from __main__ import python_style_solve, test_list") 75 | print("Python 风格执行时间: {} s".format(time_cost)) 76 | python_time.append(time_cost) 77 | 78 | time_cost = timeit.timeit("c_style_solve(test_list, len(test_list), len(test_list[0]), {})".format(number), 79 | setup="from __main__ import c_style_solve, test_list") 80 | print("C 风格执行时间: {} s".format(time_cost)) 81 | c_time.append(time_cost) 82 | 83 | print("Python 平均时间: {}, C 平均时间: {}".format(sum(python_time) / len(python_time), sum(c_time) / len(c_time))) 84 | ``` 85 | 86 | # 单元测试 87 | ```Python 88 | #!/bin/env python3 89 | # -*- coding: utf-8 -*- 90 | # version: Python3.X 91 | """ 对杨氏矩阵查找的几种解法进行单元测试 92 | """ 93 | import unittest 94 | from rectangle_search import python_style_solve, c_style_solve 95 | 96 | __author__ = '__L1n__w@tch' 97 | 98 | 99 | class TestAnswer(unittest.TestCase): 100 | def setUp(self): 101 | self.repeat_list = [[1, 2, 8, 9], [2, 4, 9, 12], [4, 7, 10, 13], [6, 8, 11, 15]] 102 | self.no_repeat_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]] 103 | 104 | def test_normal(self): 105 | # 测试数字在其中的情况 106 | wait_to_search = [1, 9, 2, 12, 4, 13, 6, 15, 11, 8, 10, 7, 9, 4, 8, 2] 107 | print("二维数组: ".format(self.repeat_list)) 108 | for each_number in wait_to_search: 109 | print("测试查找数字: {}".format(each_number)) 110 | self.failUnless(python_style_solve(self.repeat_list, each_number)) 111 | self.failUnless( 112 | c_style_solve(self.repeat_list, len(self.repeat_list), len(self.repeat_list[0]), each_number)) 113 | 114 | # 测试数字不在其中的情况 115 | # self.failIf() 116 | 117 | 118 | if __name__ == "__main__": 119 | pass 120 | ``` -------------------------------------------------------------------------------- /Python 面试编程题/5 去除列表中的重复元素/delete_repeat.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 去除列表中重复元素的几种方法 5 | """ 6 | 7 | __author__ = '__L1n__w@tch' 8 | 9 | 10 | def use_set(a_list): 11 | """ 12 | 用集合去除重复元素 13 | :param a_list: [1,2,1,2] 14 | :return: [1,2] 15 | """ 16 | return list(set(a_list)) 17 | 18 | 19 | def use_dictionary(a_list): 20 | """ 21 | 用字典去除重复元素 22 | :param a_list: [1,2,1,2] 23 | :return: [1,2] 24 | """ 25 | a_dict = dict().fromkeys(a_list).keys() 26 | return list(a_dict) 27 | 28 | 29 | def use_dict_keep_order(a_list): 30 | """ 31 | 用字典并保持顺序 32 | :param a_list: [1,2,1,2] 33 | :return: [1,2] 34 | """ 35 | another_list = list(set(a_list)) 36 | another_list.sort(key=a_list.index) 37 | return another_list 38 | 39 | 40 | def use_list_derive(a_list): 41 | """ 42 | 列表推导式 43 | :param a_list: [1,2,1,2] 44 | :return: [1,2] 45 | """ 46 | another_list = list() 47 | [another_list.append(i) for i in a_list if i not in another_list] 48 | return another_list 49 | 50 | 51 | if __name__ == "__main__": 52 | List = [1, 2, 1, 2, 3, 3, 3, 4, 1, 0, 9, 9, 3, 1111221231] 53 | 54 | print(use_set(List)) 55 | print(use_dictionary(List)) 56 | print(use_dict_keep_order(List)) 57 | print(use_list_derive(List)) 58 | 59 | if use_set(List) == use_dictionary(List) == use_dict_keep_order(List) == use_list_derive(List): 60 | print("OK") 61 | -------------------------------------------------------------------------------- /Python 面试编程题/5 去除列表中的重复元素/去除列表中的重复元素.md: -------------------------------------------------------------------------------- 1 | # 题目 2 | 去除重复元素的几种方法, 包括 3 | * 用集合去除重复元素 4 | * 用字典去除重复元素 5 | * 用字典去除并保持顺序 6 | * 列表推导式 7 | 8 | # 解答 9 | ```Python 10 | #!/bin/env python3 11 | # -*- coding: utf-8 -*- 12 | # version: Python3.X 13 | 14 | 15 | __author__ = '__L1n__w@tch' 16 | 17 | 18 | def use_set(a_list): 19 | """ 20 | 用集合去除重复元素 21 | :param a_list: [1,2,1,2] 22 | :return: [1,2] 23 | """ 24 | return list(set(a_list)) 25 | 26 | 27 | def use_dictionary(a_list): 28 | """ 29 | 用字典去除重复元素 30 | :param a_list: [1,2,1,2] 31 | :return: [1,2] 32 | """ 33 | a_dict = dict().fromkeys(a_list).keys() 34 | return list(a_dict) 35 | 36 | 37 | def use_dict_keep_order(a_list): 38 | """ 39 | 用字典并保持顺序 40 | :param a_list: [1,2,1,2] 41 | :return: [1,2] 42 | """ 43 | another_list = list(set(a_list)) 44 | another_list.sort(key=a_list.index) 45 | return another_list 46 | 47 | 48 | def use_list_derive(a_list): 49 | """ 50 | 列表推导式 51 | :param a_list: [1,2,1,2] 52 | :return: [1,2] 53 | """ 54 | another_list = list() 55 | [another_list.append(i) for i in a_list if i not in another_list] 56 | return another_list 57 | 58 | 59 | if __name__ == "__main__": 60 | List = [1, 2, 1, 2, 3, 3, 3, 4, 1, 0, 9, 9, 3, 1111221231] 61 | 62 | print(use_set(List)) 63 | print(use_dictionary(List)) 64 | print(use_dict_keep_order(List)) 65 | print(use_list_derive(List)) 66 | 67 | if use_set(List) == use_dictionary(List) == use_dict_keep_order(List) == use_list_derive(List): 68 | print("OK") 69 | ``` -------------------------------------------------------------------------------- /Python 面试编程题/6 链表成对调换/swap_pairs_list_node.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 链表成对调换 5 | 6 | 1->2->3->4 转换成 2->1->4->3 7 | 8 | 参考 GitHub 给的思路, 其实挺好理解的 9 | """ 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | def swap_pairs(head_node): 15 | """ 16 | 链表成对调换 17 | :param head_node: 18 | :return: 19 | """ 20 | if head_node is not None and head_node.next is not None: 21 | next_node = head_node.next 22 | head_node.next = swap_pairs(next_node.next) 23 | next_node.next = head_node 24 | return next_node 25 | return head_node 26 | 27 | 28 | def print_list_node(head_node): 29 | """ 30 | 顺序打印链表 31 | :param head_node: 头结点 32 | :return: None 33 | """ 34 | for node in list_node: 35 | print("No.{} List Node, Next: {}".format(node.value, node.next.value if node.next is not None else None)) 36 | print() 37 | 38 | 39 | class ListNode: 40 | def __init__(self, value, next_node=None): 41 | self.value = value 42 | self.next = next_node 43 | 44 | 45 | if __name__ == "__main__": 46 | list_node = list() 47 | for i in range(4, 0, -1): 48 | list_node.append(ListNode(i, list_node[-1] if len(list_node) > 0 else None)) 49 | list_node = list(reversed(list_node)) 50 | 51 | print_list_node(list_node[0]) 52 | 53 | swap_pairs(list_node[0]) 54 | print_list_node(list_node[0]) 55 | -------------------------------------------------------------------------------- /Python 面试编程题/6 链表成对调换/链表成对调换.md: -------------------------------------------------------------------------------- 1 | # 题目 2 | 链表成对调换 3 | 4 | `1->2->3->4` 转换成 `2->1->4->3` 5 | 6 | 通过递归实现 7 | 8 | # swap_pairs_list_node.py 9 | ```Python 10 | #!/bin/env python3 11 | # -*- coding: utf-8 -*- 12 | # version: Python3.X 13 | 14 | 15 | __author__ = '__L1n__w@tch' 16 | 17 | 18 | def swap_pairs(head_node): 19 | """ 20 | 链表成对调换 21 | :param head_node: 22 | :return: 23 | """ 24 | if head_node is not None and head_node.next is not None: 25 | next_node = head_node.next 26 | head_node.next = swap_pairs(next_node.next) 27 | next_node.next = head_node 28 | return next_node 29 | return head_node 30 | 31 | 32 | def print_list_node(head_node): 33 | """ 34 | 顺序打印链表 35 | :param head_node: 头结点 36 | :return: None 37 | """ 38 | for node in list_node: 39 | print("No.{} List Node, Next: {}".format(node.value, node.next.value if node.next is not None else None)) 40 | print() 41 | 42 | 43 | class ListNode: 44 | def __init__(self, value, next_node=None): 45 | self.value = value 46 | self.next = next_node 47 | 48 | 49 | if __name__ == "__main__": 50 | list_node = list() 51 | for i in range(4, 0, -1): 52 | list_node.append(ListNode(i, list_node[-1] if len(list_node) > 0 else None)) 53 | list_node = list(reversed(list_node)) 54 | 55 | print_list_node(list_node[0]) 56 | 57 | swap_pairs(list_node[0]) 58 | print_list_node(list_node[0]) 59 | ``` 60 | -------------------------------------------------------------------------------- /Python 面试编程题/7 创建字典的方法/create_dict.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 考怎么创建字典的? 5 | """ 6 | 7 | __author__ = '__L1n__w@tch' 8 | 9 | if __name__ == "__main__": 10 | dictionary = {"key1": 1, "key2": 2} 11 | 12 | items = [("key1", 1), ("key2", 2)] 13 | dictionary_2 = dict(items) 14 | 15 | dictionary_3 = dict().fromkeys(("key1", "key2"), -1) 16 | dictionary_4 = dict().fromkeys(("key1", "key2")) 17 | 18 | print(dictionary, dictionary_2, dictionary_3, dictionary_4) 19 | -------------------------------------------------------------------------------- /Python 面试编程题/7 创建字典的方法/创建字典的方法.md: -------------------------------------------------------------------------------- 1 | # 题目 2 | 考怎么创建字典的?包括: 3 | * 花括号创建 4 | * dict 内置类 5 | * dict().fromkeys 方法 6 | 7 | # create_dict.py 8 | ```Python 9 | #!/bin/env python3 10 | # -*- coding: utf-8 -*- 11 | # version: Python3.X 12 | 13 | 14 | __author__ = '__L1n__w@tch' 15 | 16 | if __name__ == "__main__": 17 | dictionary = {"key1": 1, "key2": 2} 18 | 19 | items = [("key1", 1), ("key2", 2)] 20 | dictionary_2 = dict(items) 21 | 22 | dictionary_3 = dict().fromkeys(("key1", "key2"), -1) 23 | dictionary_4 = dict().fromkeys(("key1", "key2")) 24 | 25 | print(dictionary, dictionary_2, dictionary_3, dictionary_4) 26 | ``` -------------------------------------------------------------------------------- /Python 面试编程题/8 合并两个有序列表/merge_sort.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 好像是考归并排序的两种实现方式, 一种递归一种循环 5 | 6 | 两种实现方式都是参考 GitHub 上的 7 | """ 8 | __author__ = '__L1n__w@tch' 9 | 10 | 11 | def recursion_merge_sort(list1, list2, a_list): 12 | def __recursion(list_wait_to_sort_1, list_wait_to_sort_2, list_after_sort): 13 | if len(list_wait_to_sort_1) == 0 or len(list_wait_to_sort_2) == 0: 14 | list_after_sort.extend(list_wait_to_sort_1) 15 | list_after_sort.extend(list_wait_to_sort_2) 16 | return list_after_sort 17 | elif list_wait_to_sort_1[0] < list_wait_to_sort_2[0]: 18 | list_after_sort.append(list_wait_to_sort_1[0]) 19 | del list_wait_to_sort_1[0] # 为啥不用 list1.pop(0)... 20 | elif list_wait_to_sort_1[0] >= list_wait_to_sort_2[0]: 21 | list_after_sort.append(list_wait_to_sort_2[0]) 22 | del list_wait_to_sort_2[0] 23 | return __recursion(list_wait_to_sort_1, list_wait_to_sort_2, list_after_sort) 24 | 25 | return __recursion(list1, list2, list()) 26 | 27 | 28 | def loop_merge_sort(list1, list2): 29 | after_sort = list() 30 | while len(list1) > 0 and len(list2) > 0: 31 | if list1[0] < list2[0]: 32 | after_sort.append(list1[0]) 33 | del list1[0] 34 | else: 35 | after_sort.append(list2[0]) 36 | del list2[0] 37 | after_sort.extend(list1) 38 | after_sort.extend(list2) 39 | return after_sort 40 | 41 | 42 | if __name__ == "__main__": 43 | List1 = sorted([3, 4, 1, 2]) 44 | List2 = sorted([2, 1, 1, 1]) 45 | 46 | test_list = recursion_merge_sort(List1[::1], List2[::1], list()) 47 | print(test_list) 48 | 49 | test_list = loop_merge_sort(List1, List2) 50 | print(test_list) 51 | -------------------------------------------------------------------------------- /Python 面试编程题/8 合并两个有序列表/unittest_merge_sort.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 测试归并排序是否正确 5 | """ 6 | import random 7 | import unittest 8 | from merge_sort import recursion_merge_sort, loop_merge_sort 9 | 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | class TestMergeSort(unittest.TestCase): 15 | def test(self): 16 | for i in range(5): 17 | wait_to_sort = sorted([random.randint(-1000, 1000) for i in range(100)]) 18 | wait_to_sort_2 = sorted([random.randint(-1000, 1000) for i in range(100)]) 19 | 20 | after_sort = sorted(wait_to_sort + wait_to_sort_2) 21 | 22 | self.failUnless(after_sort == recursion_merge_sort(wait_to_sort[::1], wait_to_sort_2[::1], list())) 23 | self.failUnless(after_sort == loop_merge_sort(wait_to_sort[::1], wait_to_sort_2[::1])) 24 | 25 | 26 | if __name__ == "__main__": 27 | pass 28 | -------------------------------------------------------------------------------- /Python 面试编程题/8 合并两个有序列表/合并两个有序列表.md: -------------------------------------------------------------------------------- 1 | # 题目 2 | 考归并排序的两种实现方式, 一种递归一种循环 3 | 4 | # merge_sort.py 5 | ```Python 6 | #!/bin/env python3 7 | # -*- coding: utf-8 -*- 8 | # version: Python3.X 9 | 10 | __author__ = '__L1n__w@tch' 11 | 12 | 13 | def recursion_merge_sort(list1, list2, a_list): 14 | def __recursion(list_wait_to_sort_1, list_wait_to_sort_2, list_after_sort): 15 | if len(list_wait_to_sort_1) == 0 or len(list_wait_to_sort_2) == 0: 16 | list_after_sort.extend(list_wait_to_sort_1) 17 | list_after_sort.extend(list_wait_to_sort_2) 18 | return list_after_sort 19 | elif list_wait_to_sort_1[0] < list_wait_to_sort_2[0]: 20 | list_after_sort.append(list_wait_to_sort_1[0]) 21 | del list_wait_to_sort_1[0] # 为啥不用 list1.pop(0)... 22 | elif list_wait_to_sort_1[0] >= list_wait_to_sort_2[0]: 23 | list_after_sort.append(list_wait_to_sort_2[0]) 24 | del list_wait_to_sort_2[0] 25 | return __recursion(list_wait_to_sort_1, list_wait_to_sort_2, list_after_sort) 26 | 27 | return __recursion(list1, list2, list()) 28 | 29 | 30 | def loop_merge_sort(list1, list2): 31 | after_sort = list() 32 | while len(list1) > 0 and len(list2) > 0: 33 | if list1[0] < list2[0]: 34 | after_sort.append(list1[0]) 35 | del list1[0] 36 | else: 37 | after_sort.append(list2[0]) 38 | del list2[0] 39 | after_sort.extend(list1) 40 | after_sort.extend(list2) 41 | return after_sort 42 | 43 | 44 | if __name__ == "__main__": 45 | List1 = sorted([3, 4, 1, 2]) 46 | List2 = sorted([2, 1, 1, 1]) 47 | 48 | test_list = recursion_merge_sort(List1[::1], List2[::1], list()) 49 | print(test_list) 50 | 51 | test_list = loop_merge_sort(List1, List2) 52 | print(test_list) 53 | ``` 54 | 55 | # 单元测试 56 | ```Python 57 | #!/bin/env python3 58 | # -*- coding: utf-8 -*- 59 | # version: Python3.X 60 | """ 测试归并排序是否正确 61 | """ 62 | import random 63 | import unittest 64 | from merge_sort import recursion_merge_sort, loop_merge_sort 65 | 66 | 67 | __author__ = '__L1n__w@tch' 68 | 69 | 70 | class TestMergeSort(unittest.TestCase): 71 | def test(self): 72 | for i in range(5): 73 | wait_to_sort = sorted([random.randint(-1000, 1000) for i in range(100)]) 74 | wait_to_sort_2 = sorted([random.randint(-1000, 1000) for i in range(100)]) 75 | 76 | after_sort = sorted(wait_to_sort + wait_to_sort_2) 77 | 78 | self.failUnless(after_sort == recursion_merge_sort(wait_to_sort[::1], wait_to_sort_2[::1], list())) 79 | self.failUnless(after_sort == loop_merge_sort(wait_to_sort[::1], wait_to_sort_2[::1])) 80 | 81 | 82 | if __name__ == "__main__": 83 | pass 84 | ``` -------------------------------------------------------------------------------- /Python 面试编程题/9 二分查找/binary_search.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 考二分查找法的 5 | """ 6 | 7 | __author__ = '__L1n__w@tch' 8 | 9 | 10 | def binary_search(a_list, number_to_find): 11 | """ 12 | 二分查找法 13 | :param a_list: 待查找列表 14 | :param number_to_find: 待查找数字 15 | :return: int() or False 16 | """ 17 | start, end = 0, len(a_list) - 1 18 | while start < end: 19 | middle = (start + end) // 2 20 | if a_list[middle] > number_to_find: 21 | end = middle 22 | elif a_list[middle] < number_to_find: 23 | start = middle + 1 24 | else: 25 | return middle 26 | return start if a_list[start] == number_to_find else False 27 | 28 | 29 | if __name__ == "__main__": 30 | List = [i for i in range(10)] 31 | print(binary_search(List, 2)) 32 | -------------------------------------------------------------------------------- /Python 面试编程题/9 二分查找/unittest_binary_search.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 单元测试二分查找 5 | """ 6 | import random 7 | import unittest 8 | from binary_search import binary_search 9 | 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | class TestBinarySearch(unittest.TestCase): 15 | def test(self): 16 | list_wait_to_search = sorted([random.randint(-1000, 1000) for i in range(100)]) 17 | number_wait_to_search = list_wait_to_search[random.randint(0, 100)] 18 | 19 | self.failUnless(number_wait_to_search == 20 | list_wait_to_search[binary_search(list_wait_to_search, number_wait_to_search)]) 21 | -------------------------------------------------------------------------------- /Python 面试编程题/9 二分查找/二分查找.md: -------------------------------------------------------------------------------- 1 | # 题目 2 | 考二分查找法的 3 | 4 | # binary_search.py 5 | ```Python 6 | #!/bin/env python3 7 | # -*- coding: utf-8 -*- 8 | # version: Python3.X 9 | 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | def binary_search(a_list, number_to_find): 15 | """ 16 | 二分查找法 17 | :param a_list: 待查找列表 18 | :param number_to_find: 待查找数字 19 | :return: int() or False 20 | """ 21 | start, end = 0, len(a_list) - 1 22 | while start < end: 23 | middle = (start + end) // 2 24 | if a_list[middle] > number_to_find: 25 | end = middle 26 | elif a_list[middle] < number_to_find: 27 | start = middle + 1 28 | else: 29 | return middle 30 | return start if a_list[start] == number_to_find else False 31 | 32 | 33 | if __name__ == "__main__": 34 | List = [i for i in range(10)] 35 | print(binary_search(List, 2)) 36 | ``` 37 | 38 | # 单元测试 39 | ```Python 40 | #!/bin/env python3 41 | # -*- coding: utf-8 -*- 42 | # version: Python3.X 43 | """ 单元测试二分查找 44 | """ 45 | import random 46 | import unittest 47 | from binary_search import binary_search 48 | 49 | 50 | __author__ = '__L1n__w@tch' 51 | 52 | 53 | class TestBinarySearch(unittest.TestCase): 54 | def test(self): 55 | list_wait_to_search = sorted([random.randint(-1000, 1000) for i in range(100)]) 56 | number_wait_to_search = list_wait_to_search[random.randint(0, 100)] 57 | 58 | self.failUnless(number_wait_to_search == 59 | list_wait_to_search[binary_search(list_wait_to_search, number_wait_to_search)]) 60 | ``` -------------------------------------------------------------------------------- /Python 面试编程题/readme.md: -------------------------------------------------------------------------------- 1 | # Python 面试编程题 2 | 这一节主要就是编程题部分。 3 | ## 参考资料 4 | [interview_python](https://github.com/taizilongxu/interview_python#1-%E5%8F%B0%E9%98%B6%E9%97%AE%E9%A2%98%E6%96%90%E6%B3%A2%E7%BA%B3%E6%8C%88) 5 | ## 清单 6 | 1. 台阶问题/斐波那契 7 | 2. 变态台阶问题 8 | 3. 矩形覆盖 9 | 4. 杨氏矩阵查找 10 | 5. 去除列表中的重复元素 11 | 6. 链表成对调换 12 | 7. 创建字典的方法 13 | 8. 合并两个有序列表 14 | 9. 二分查找 15 | 10. 快排 16 | 11. 找零问题 17 | 12. 二叉树相关 18 | 13. 单链表逆置 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python && C/C++ 面试 2 | 3 | 整理自己准备 Python && C/C++ 面试时的相关资料 4 | 5 | [GitBook 链接](https://l1nwatch.gitbooks.io/interview_exercise/content/) 6 | 7 | 【PS: 突然发现 Python Cookbook 很适合拿来当考题, 以后我要是面试别人就用这个出题, ✧(≖ ◡ ≖✿)嘿嘿】[Python CookBook](http://python3-cookbook.readthedocs.io/zh_CN/latest/index.html) 8 | 9 | # 资料来源 10 | 11 | * [牛客网](http://www.nowcoder.com/7651698) 12 | * [GitHub Python 面试题](https://github.com/taizilongxu/interview_python) 13 | * [GitHub stackoverflow-about-Python](https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/) 14 | * [Python CookBook](http://python3-cookbook.readthedocs.io/zh_CN/latest/index.html) 15 | * sangfor -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [说明](README.md) 4 | * [C/C++ 问答题汇总](C_问答题汇总.md) 5 | * [编程题汇总](编程题汇总.md) 6 | * [腾讯 2017 暑期实习生编程题](腾讯 2017 暑期实习生编程题/腾讯 2017 暑期实习生编程题.md) 7 | * [构造回文](腾讯 2017 暑期实习生编程题/构造回文.md) 8 | * [算法基础-字符移位](腾讯 2017 暑期实习生编程题/算法基础-字符移位.md) 9 | * [有趣的数字](腾讯 2017 暑期实习生编程题/有趣的数字.md) 10 | * [剑指 Offer 编程题练习](剑指 Offer 编程题/readme.md) 11 | * [二维数组中的查找](剑指 Offer 编程题/二维数组中的查找/readme.md) 12 | * [从尾到头打印链表](剑指 Offer 编程题/从尾到头打印链表/readme.md) 13 | * [旋转数组的最小数字](剑指 Offer 编程题/旋转数组的最小数字/readme.md) 14 | * [替换空格](剑指 Offer 编程题/替换空格/readme.md) 15 | * [用两个栈实现队列](剑指 Offer 编程题/用两个栈实现队列/readme.md) 16 | * [重建二叉树](剑指 Offer 编程题/重建二叉树/readme.md) 17 | * [网易 2017 校招笔试编程题](网易 2017 校招笔试编程题/readme.md) 18 | * [二进制权重](网易 2017 校招笔试编程题/二进制权重.md) 19 | * [平方串](网易 2017 校招笔试编程题/平方串.md) 20 | * [数位和](网易 2017 校招笔试编程题/数位和.md) 21 | * [安全测试开发相关面试](安全测试开发相关面试/readme.md) 22 | * [安全测试类面试参考](安全测试开发相关面试/安全测试类面试参考/readme.md) 23 | * [业务安全类面试参考](安全测试开发相关面试/业务安全类面试参考/readme.md) 24 | * [测试开发类面试参考](安全测试开发相关面试/测试开发类面试参考/readme.md) 25 | * [深信服_sangfor_相关](深信服_sangfor_相关/readme.md) 26 | * [深信服acm相关](深信服_sangfor_相关/sangfor_acm_oj/readme.md) 27 | * [测试类面试参考](深信服_sangfor_相关/测试类面试参考.md) 28 | * [智安全杯](深信服_sangfor_相关/智安全杯/readme.md) 29 | * [智安全杯-2018比赛](深信服_sangfor_相关/智安全杯/2018比赛.md) 30 | * [智安全杯-2019初赛](深信服_sangfor_相关/智安全杯/2019初赛.md) 31 | * [智安全杯-2019复赛](深信服_sangfor_相关/智安全杯/2019复赛.md) 32 | * [软件测试题汇总](软件测试题/题目汇总.md) 33 | * [计算机知识题汇总](计算机知识/readme.md) 34 | * [前 75 题](计算机知识/readme1.md) 35 | * [75 题以后](计算机知识/readme2.md) 36 | * [Python 语言特性](Python 语言特性/readme.md) 37 | * [1 Python的函数参数传递](Python 语言特性/1 Python的函数参数传递.md) 38 | * [2 @staticmethod和@classmethod](Python 语言特性/2 @staticmethod和@classmethod.md) 39 | * [3 类变量和实例变量](Python 语言特性/3 类变量和实例变量.md) 40 | * [4 Python中单下划线和双下划线](Python 语言特性/4 Python中单下划线和双下划线.md) 41 | * [5 *args and **kwargs](Python 语言特性/5 args and kwargs.md) 42 | * [6 面向切面编程AOP和装饰器](Python 语言特性/6 面向切面编程AOP和装饰器.md) 43 | * [7 单例模式](Python 语言特性/7 单例模式.md) 44 | * [8 Python 函数式编程](Python 语言特性/8 Python 函数式编程.md) 45 | * [9 Python 里的拷贝](Python 语言特性/9 Python 里的拷贝.md) 46 | * [stackoverflow-about-Python](stackoverflow-about-Python/readme.md) 47 | * [Python中关键字yield有什么作用?](stackoverflow-about-Python/Python中关键字yield有什么作用.md) 48 | * [Python中的元类(metaclass)是什么?](stackoverflow-about-Python/Python中的元类(metaclass)是什么.md) 49 | * [Python中如何在一个函数中加入多个装饰器?](stackoverflow-about-Python/Python中如何在一个函数中加入多个装饰器.md) 50 | * [如何判断一个文件是否存在?](stackoverflow-about-Python/如何判断一个文件是否存在.md) 51 | * [如何调用外部命令?](stackoverflow-about-Python/如何调用外部命令.md) 52 | * [枚举类型的使用?](stackoverflow-about-Python/枚举类型的使用.md) 53 | * [在Windows下安装pip?](stackoverflow-about-Python/在Windows下安装pip.md) 54 | * [字典合并问题](stackoverflow-about-Python/字典合并问题.md) 55 | * [在Android上运行Python](stackoverflow-about-Python/在Android上运行Python.md) 56 | * [根据字典值进行排序](stackoverflow-about-Python/根据字典值进行排序.md) 57 | * [在函数里使用全局变量](stackoverflow-about-Python/在函数里使用全局变量.md) 58 | * [变化的默认参数](stackoverflow-about-Python/变化的默认参数.md) 59 | * [装饰器classmethod和staticmethod的区别](stackoverflow-about-Python/装饰器classmethod和staticmethod的区别.md) 60 | * [检查列表为空的最好办法](stackoverflow-about-Python/检查列表为空的最好办法.md) 61 | * [怎么用引用来改变一个变量](stackoverflow-about-Python/怎么用引用来改变一个变量.md) 62 | * [检查文件夹是否存在的操作](stackoverflow-about-Python/检查文件夹是否存在的操作.md) 63 | * [name=main的作用](stackoverflow-about-Python/name=main的作用.md) 64 | * [super与init方法](stackoverflow-about-Python/super与init方法.md) 65 | * [str与repr的区别](stackoverflow-about-Python/str与repr的区别.md) 66 | * [循环中获取索引](stackoverflow-about-Python/循环中获取索引.md) 67 | * [类里的静态变量](stackoverflow-about-Python/类里的静态变量.md) 68 | * [怎么在终端里输出颜色?](stackoverflow-about-Python/怎么在终端里输出颜色.md) 69 | * [为什么用pip比用easy_install的好?](stackoverflow-about-Python/为什么用pip比用easy_install的好.md) 70 | * [join的问题](stackoverflow-about-Python/join的问题.md) 71 | * [把列表分割成同样大小的块](stackoverflow-about-Python/把列表分割成同样大小的块.md) 72 | * [为什么代码在一个函数里运行的更快](stackoverflow-about-Python/为什么代码在一个函数里运行的更快.md) 73 | * [如何快速合并列表中的列表?](stackoverflow-about-Python/快速合并列表中的列表.md) 74 | * [如何知道一个对象有一个特定的属性?](stackoverflow-about-Python/如何知道一个对象有一个特定的属性.md) 75 | * [如何通过函数名的字符串来调用这个函数?](stackoverflow-about-Python/如何通过函数名的字符串来调用函数.md) 76 | * [单下划线和双下划线的含义?](stackoverflow-about-Python/单下划线和双下划线的含义.md) 77 | * [Python 面试编程题](Python 面试编程题/readme.md) 78 | * [1 台阶问题 斐波那契](Python 面试编程题/1 台阶问题 斐波那契/斐波那契.md) 79 | * [2 变态台阶问题](Python 面试编程题/2 变态台阶问题/变态台阶问题.md) 80 | * [3 矩形覆盖](Python 面试编程题/3 矩形覆盖/矩阵覆盖.md) 81 | * [4 杨氏矩阵查找](Python 面试编程题/4 杨氏矩阵查找/杨氏矩阵查找.md) 82 | * [5 去除列表中的重复元素](Python 面试编程题/5 去除列表中的重复元素/去除列表中的重复元素.md) 83 | * [6 链表成对调换](Python 面试编程题/6 链表成对调换/链表成对调换.md) 84 | * [7 创建字典的方法](Python 面试编程题/7 创建字典的方法/创建字典的方法.md) 85 | * [8 合并两个有序列表](Python 面试编程题/8 合并两个有序列表/合并两个有序列表.md) 86 | * [9 二分查找](Python 面试编程题/9 二分查找/二分查找.md) 87 | * [10 快排](Python 面试编程题/10 快排/快排.md) 88 | * [11 找零问题](Python 面试编程题/11 找零问题/找零问题.md) 89 | * [12 二叉树相关](Python 面试编程题/12 二叉树相关/二叉树相关.md) 90 | * [13 单链表逆置](Python 面试编程题/13 单链表逆置/单链表逆置.md) -------------------------------------------------------------------------------- /python_script/check_summary.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 2017.03.10 使用博客搜索本仓库下某个文件夹的笔记才发现, 存在 summary.md 与路径对应不上的问题, 于是编写脚本来检查 6 | """ 7 | import os 8 | import re 9 | 10 | __author__ = '__L1n__w@tch' 11 | 12 | 13 | class Checker: 14 | def run(self, summary_md_file_path, root_path): 15 | """ 16 | 进行所有检查 17 | :param summary_md_file_path: str(), 比如 "SUMMARY.md", 表示 SUMMARY.md 的路径 18 | :param root_path: str(), 比如 "/Users/.../interview_collect", 表示所有 md 文件的根路径 19 | :return: None 20 | """ 21 | # 打开 summary.md, 加载所有目录对应的路径 22 | path_list = self.get_all_path_in_summary_md_file(summary_md_file_path) 23 | 24 | # 遍历每个路径, 看对应的文件是否存在 25 | for each_path in path_list: 26 | if not os.path.exists(os.path.join(root_path, each_path)): 27 | print("[-] Error: 路径 {} 不存在".format(each_path)) 28 | 29 | @staticmethod 30 | def get_all_path_in_summary_md_file(md_file_path): 31 | """ 32 | 通过读取 summary.md 提取出所有要进行判定的路径 33 | :param md_file_path: str(), 比如 "SUMMARY.md", 指定 SUMMARY.md 的路径 34 | :return: list(), 比如 ["README.md", "腾讯 2017 暑期实习生编程题/腾讯 2017 暑期实习生编程题.md", ...] 35 | """ 36 | result_list = list() 37 | title_re = re.compile("\[.*\]\((.*)\)") 38 | 39 | with open(md_file_path, "r",encoding="utf8") as f: 40 | for each_line in f: 41 | re_result = title_re.findall(each_line) 42 | if re_result: 43 | result_list.append(re_result[0]) 44 | 45 | return result_list 46 | 47 | 48 | if __name__ == "__main__": 49 | base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 50 | summary_path = os.path.join(base_dir, "SUMMARY.md") 51 | 52 | check = Checker() 53 | check.run(summary_path, base_dir) 54 | -------------------------------------------------------------------------------- /python_script/readme.md: -------------------------------------------------------------------------------- 1 | ## 文件夹说明 2 | 3 | 这个文件夹存放一些 Python 脚本, 用于辅助本仓库的维护等工作 4 | 5 | ### 清单 6 | 7 | * `search_keyword`: 实现对本仓库内容进行搜索的脚本 8 | 9 | * `check_summary`: 检查 `summary.md` 中的路径信息是否跟文件夹中的路径信息相对应 -------------------------------------------------------------------------------- /python_script/search_keyword.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 实现对指定文件夹下所有文件进行内容搜索, 关键词及搜索的文件类型由用户指定 5 | 6 | 2016.07.23 由于自己现在记的笔记形式是 GitHub + GitBook, 但是这两货的笔记搜索功能是在有限, 故需要将此程序进一步扩展 7 | 2016.06.21 由于微机原理也要进行 ARM 平台小车的开发, 遇到了跟 ZigBee 一样的困境, 需要快速掌握工程文件, 所以还是将这个程序通用化吧 8 | 2016.04 起初编写这个程序是由于对协议栈不熟悉, 所以需要对协议栈的每一个文件进行关键词搜索, 同时列举出来 9 | """ 10 | import os 11 | import argparse 12 | 13 | __author__ = '__L1n__w@tch' 14 | 15 | 16 | def is_valid_file_type(name, types): 17 | """ 18 | :param name: 文件名, 比如 '.DS_Store' 19 | :param types: 要搜寻的文件类型, 比如 [".h", ".c"] 20 | :return: False 21 | """ 22 | name = name.lower() 23 | for each_type in types: 24 | if name.endswith(each_type): 25 | return True 26 | return False 27 | 28 | 29 | def add_argument(parser): 30 | """ 31 | 为解析器添加参数 32 | :param parser: ArgumentParser 实例对象 33 | :return: None 34 | """ 35 | parser.add_argument("--path", "-p", type=str, 36 | default=os.curdir, help="文件夹路径") 37 | parser.add_argument("--type", "-t", type=str, default=".c#.h#.cpp#.py#.md", 38 | help="搜索文件类型, 默认值及格式为: \".c#.h#.cpp#.py#.md\"") 39 | parser.add_argument("--keyword", "-k", type=str, default="main", help="要搜索的关键词") 40 | 41 | 42 | def set_argument(options): 43 | """ 44 | 读取用户输入的参数, 检验是否合法 45 | :param options: parser.opts 46 | :return: dict() 47 | """ 48 | configuration = dict() 49 | configuration["path"] = options.path 50 | configuration["file_type"] = options.type.split("#") 51 | # configuration["keyword"] = options.keyword.lower() 52 | 53 | print("[*] 要搜索的路径为: {}".format(configuration["path"])) 54 | print("[*] 要搜索的文件类型包括: {}".format(configuration["file_type"])) 55 | # print("[*] 要搜索的关键词为: {}".format(configuration["keyword"])) 56 | 57 | return configuration 58 | 59 | 60 | def initialize(): 61 | """ 62 | 进行初始化操作, 包括 argparse 解析程序的初始化, 参数的相关设定等 63 | :return: path, file_type, keyword 64 | """ 65 | parser = argparse.ArgumentParser(description="文件内容搜索程序") 66 | add_argument(parser) 67 | configuration = set_argument(parser.parse_args()) 68 | 69 | print("[*] {} 搜索开始 {}".format("-" * 30, "-" * 30)) 70 | 71 | return configuration["path"], configuration["file_type"] 72 | 73 | 74 | def search_keyword_infile(file_path, word): 75 | """ 76 | 判断一个文件内是否含有该关键词, 并且把含有该关键词的那一行返回回去 77 | :param file_path: 文件路径, 比如 './compare_key.py' 78 | :param word: "main" 79 | :return: 返回含有关键词的那一行, 或者返回 None 表示找不到, 即 None or "int main()" 80 | """ 81 | # word 处理 82 | word = word.lower() 83 | word = word.encode("utf8") 84 | 85 | with open(path, "rb") as f: 86 | data = f.readlines() 87 | 88 | for each_line in data: 89 | if word in each_line.lower(): 90 | return each_line 91 | return None 92 | 93 | 94 | if __name__ == "__main__": 95 | path, file_type = initialize() 96 | keyword = input("[?] 请输入要搜索的关键词: ") 97 | 98 | for root, dirs, files in os.walk(path): 99 | for each_file in files: 100 | if is_valid_file_type(each_file, file_type): 101 | path = root + os.sep + each_file 102 | line_content = search_keyword_infile(path, keyword) 103 | if line_content: 104 | print("[*] Found in \"{}\", path is \033[95m{}\033[0m".format(each_file, path)) 105 | print("[*] {}\033[91m{}\033[0m".format("\t" * 4, line_content.decode("utf8").strip())) 106 | print("[*] {} 搜索结束 {}".format("-" * 30, "-" * 30)) 107 | -------------------------------------------------------------------------------- /python_script/test_check_summary.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 2017.03.10 作为 check_summary 的测试文件, 具体实现参考博客源码 6 | """ 7 | import unittest 8 | import os 9 | from check_summary import Checker 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | class Tester(unittest.TestCase): 15 | def setUp(self): 16 | self.base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | self.test_check = Checker() 18 | 19 | def test_get_title_list_from_summary(self): 20 | """ 21 | 测试函数是否获取正确 22 | """ 23 | summary_path = os.path.join(self.base_dir, "SUMMARY.md") 24 | title_list = self.test_check.get_all_path_in_summary_md_file(summary_path) 25 | 26 | self.assertIn("README.md", title_list) 27 | self.assertIn("腾讯 2017 暑期实习生编程题/腾讯 2017 暑期实习生编程题.md", title_list) 28 | self.assertIn("软件测试题/题目汇总.md", title_list) 29 | self.assertIn("Python 语言特性/3 类变量和实例变量.md", title_list) 30 | self.assertIn("Python 面试编程题/13 单链表逆置/单链表逆置.md", title_list) 31 | 32 | 33 | if __name__ == "__main__": 34 | pass 35 | -------------------------------------------------------------------------------- /stackoverflow-about-Python/Python中关键字yield有什么作用.md: -------------------------------------------------------------------------------- 1 | ## Python中关键字yield有什么作用? 2 | 3 | 为了理解 yield 有什么用,首先得理解 generators,再之前还要理解 iterables 4 | 5 | ### Iterables 6 | 7 | 可迭代的,比如创建了一个列表,可以一个一个读取它的每一项,这就叫迭代(iteration): 8 | 9 | ```python 10 | >>> mylist = [1, 2, 3] 11 | >>> for i in mylist: 12 | ... print(i) 13 | 1 14 | 2 15 | 3 16 | ``` 17 | 18 | 可以用在 `for...in...` 语句中的都是可迭代的,但是必须把它们的值放到内存里,当它们有很多值时就会消耗太多的内存 19 | 20 | ### Generators 21 | 22 | 生成器,也是迭代器的一种,但是只能迭代一次,因为它们不是全部存在内存里,只在要调用的时候在内存里生成: 23 | 24 | ```python 25 | >>> mygenerator = (x*x for x in range(3)) 26 | >>> for i in mygenerator: 27 | ... print(i) 28 | 0 29 | 1 30 | 4 31 | ``` 32 | 33 | 生成器和迭代器的区别就是用 `()` 代替 `[]`,还有不能用 `for i in mygenerator` 第二次调用生成器,因为每计算完一个值就会丢弃一个值 34 | 35 | ### Yield 36 | 37 | `yield` 用法和 `return` 差不多,下面的函数将会返回一个生成器: 38 | 39 | ```python 40 | >>> def createGenerator(): 41 | ... mylist = range(3) 42 | ... for i in mylist: 43 | ... yield i*i 44 | ... 45 | >>> mygenerator = createGenerator() # 创建生成器 46 | >>> print(mygenerator) # mygenerator is an object! 47 | 48 | >>> for i in mygenerator: 49 | ... print(i) 50 | 0 51 | 1 52 | 4 53 | ``` 54 | 55 | 如果函数要返回一个非常大的集合,而你只需要读取一次的话,用这个就很合适了。 56 | 57 | 这里当你调用函数时,函数里的代码并没有运行,仅仅返回生成器对象。每当 for 语句迭代生成器的时候代码才会运转。 58 | 59 | 当 `for` 语句第一次调用函数里的生成器对象,函数里的代码就开始运作,直到碰到 `yield`,然后会返回本次循环的第一个返回值。所以下一次调用也将运行一次循环然后返回下一个值,直到没有值可以返回。一旦函数运行没有喷到 yield 语句就认为生成器已经为空了 60 | 61 | ### 生成器的高级用法:控制迭代器的穷尽 62 | 63 | 生成器对于一些不断变化的值很有用,比如控制资源的访问: 64 | 65 | ```python 66 | >>> class Bank(): # 让我们建个银行,生产许多ATM 67 | ... crisis = False 68 | ... def create_atm(self): 69 | ... while not self.crisis: 70 | ... yield "$100" 71 | >>> hsbc = Bank() # 当一切就绪了你想要多少ATM就给你多少 72 | >>> corner_street_atm = hsbc.create_atm() 73 | >>> print([corner_street_atm.next() for cash in range(5)]) 74 | ['$100', '$100', '$100', '$100', '$100'] 75 | >>> hsbc.crisis = True # 经济危机来了没有钱了! 76 | >>> print(corner_street_atm.next()) 77 | 78 | >>> wall_street_atm = hsbc.create_atm() # 对于其他ATM,它还是True 79 | >>> print(wall_street_atm.next()) 80 | 81 | >>> hsbc.crisis = False # 麻烦的是,尽管危机过去了,ATM还是空的 82 | >>> print(corner_street_atm.next()) 83 | 84 | >>> brand_new_atm = hsbc.create_atm() # 只能重新新建一个bank了 85 | >>> for cash in brand_new_atm: 86 | ... print cash 87 | $100 88 | $100 89 | ``` 90 | 91 | ### Itertools 模块 92 | 93 | 该模块包含了一些特殊的函数可以操作可迭代对象,比如复制生成器,链接两个生成器等 94 | 95 | ```python 96 | >>> horses = [1, 2, 3, 4] 97 | >>> races = itertools.permutations(horses) 98 | >>> print(races) 99 | >>> print(list(itertools.permutations(horses))) 100 | [(1, 2, 3, 4), 101 | (1, 2, 4, 3), 102 | (1, 3, 2, 4), 103 | (1, 3, 4, 2), 104 | (1, 4, 2, 3), 105 | .... 106 | ] 107 | ``` 108 | 109 | ### 理解迭代的内部机制 110 | 111 | 迭代是可迭代对象(对应 `__iter__()` 方法)和迭代器(对应 `__next__()` 方法)的一个过程。 -------------------------------------------------------------------------------- /stackoverflow-about-Python/join的问题.md: -------------------------------------------------------------------------------- 1 | ## join的问题 2 | 3 | 为什么是 `string.join(list)` 而不是 `list.join(string)`? 4 | 5 | 比如: 6 | 7 | ```python 8 | my_list = ["Hello", "world"] 9 | print(my_list.join("-")) 10 | # Produce: "Hello-world" 11 | ``` 12 | 13 | 其实因为所有的可迭代对象都能被 `join`,不仅仅是列表,但一般情况下我们要 `join` 的都是字符串 14 | 15 | 比如: 16 | 17 | ```python 18 | import urllib2 19 | print '\n############\n'.join(urllib2.urlopen('http://data.stackexchange.com/users/7095')) 20 | ``` 21 | 22 | -------------------------------------------------------------------------------- /stackoverflow-about-Python/name=main的作用.md: -------------------------------------------------------------------------------- 1 | ## name=main的作用 2 | 3 | 当 Python 解析器读取一个源文件时,它会执行所有的代码。在执行代码前,会定义一些特殊的变量。如果解析器运行的模块(源文件)作为主程序,它会把 `__name__` 变量设置成 `__main__`,如果只是引入其他的模块,`__name__` 变量将会设置成模块的名字 4 | 5 | 这么做的原因是有时你需要你写的模块既可以直接执行,还可以被当做模块导入到其他模块中去。通过检查是不是主函数,可以让你的代码只在它作为主程序运行时执行,而当其他人调用你的模块中的函数时不必执行 6 | 7 | 更多详情可以查看该[网址](http://ibiblio.org/g2swap/byteofpython/read/module-name.html) -------------------------------------------------------------------------------- /stackoverflow-about-Python/readme.md: -------------------------------------------------------------------------------- 1 | ## 说明 2 | 3 | 记录一下学习 pdf: stackoverflow-about-Python 的笔记 4 | 5 | 资料链接: [https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/](https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/) -------------------------------------------------------------------------------- /stackoverflow-about-Python/str与repr的区别.md: -------------------------------------------------------------------------------- 1 | ## str与repr的区别 2 | 3 | 有一点是可以肯定的:如果 `__repr__` 被定义而 `__str__` 没有,那么对象会自动设置 `__str__ = __repr__` 4 | 5 | 这意味着,几乎所有的对象你需要实现 `__repr__` 以便使用者更好地理解这个对象。然而实现 `__str__` 只是为了一个更漂亮的输出 6 | 7 | 实现 `__repr__` 是为了明确 8 | 9 | 实现 `__str__` 是为了可读性 10 | 11 | -------------------------------------------------------------------------------- /stackoverflow-about-Python/super与init方法.md: -------------------------------------------------------------------------------- 1 | ## super与init方法 2 | 3 | `super()` 的好处是可以避免直接使用父类的名字,主要用于多重继承。 4 | 5 | 注意在 Python3 里面语法有所改变,可以用 `super().__init___()` 代替 `super(ChildB, self).__init__()` 6 | 7 | DEMO: 8 | 9 | ```python 10 | class Base(object): 11 | def __init__(self): 12 | print "Base created" 13 | 14 | class ChildA(Base): 15 | def __init__(self): 16 | Base.__init__(self) 17 | 18 | class ChildB(Base): 19 | def __init__(self): 20 | super(ChildB, self).__init__() 21 | 22 | class ChildC(Base): 23 | def __init__(self): 24 | super().__init__() 25 | 26 | print ChildA(), ChildB(), ChildC() 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /stackoverflow-about-Python/为什么代码在一个函数里运行的更快.md: -------------------------------------------------------------------------------- 1 | ## 为什么代码在一个函数里运行的更快? 2 | 3 | 比如同样的一段代码,放在函数里: 4 | 5 | ```python 6 | def main(): 7 | for i in xrange(10**8): 8 | pass 9 | main() 10 | ``` 11 | 12 | 运行时间: 13 | 14 | ```shell 15 | real 0m1.841s 16 | user 0m1.828s 17 | sys 0m0.012s 18 | ``` 19 | 20 | 不放在函数里: 21 | 22 | ```python 23 | for i in xrange(10**8): 24 | pass 25 | ``` 26 | 27 | 运行时间: 28 | 29 | ```shell 30 | real 0m4.543s 31 | user 0m4.524s 32 | sys 0m0.012s 33 | ``` 34 | 35 | ### 解答 36 | 37 | 这是因为存取一个本地变量比全局变量要快,这有关 CPython 的实现细节。 38 | 39 | 记住 CPython 解析器运行的是被编译过的字节编码(bytecode)。当一个函数被编译后,局部变量被存储在了固定大小的数组(不是一个 dict),而变量名赋值给了索引。于是你不能动态地为一个函数添加局部变量,检查一个局部变量就好像是一个指针去查找列表,对于在 PyObject 上的引用计数增长是微不足道的 40 | 41 | 在查找全局变量(`LOAD_GLOBAL`)时,涉及到一个实实在在的 dict 的哈希查找。同时,这也是你想要一个全局变量时需要加上 `global i` 的原因:如果你在一个区域内指定变量,编译器就会建立一个 `STORE_FAST` 的入口,除非你不让它这么做。 42 | 43 | 全局查找速度其实也不慢,真正拖慢速度的是像 `foo.bar` 这样的属性查找 44 | 45 | *** 46 | 47 | 对比函数和全局的字节码: 48 | 49 | ```python 50 | # 函数 51 | 2 0 SETUP_LOOP 20 (to 23) 52 | 3 LOAD_GLOBAL 0 (xrange) 53 | 6 LOAD_CONST 3 (100000000) 54 | 9 CALL_FUNCTION 1 55 | 12 GET_ITER 56 | >> 13 FOR_ITER 6 (to 22) 57 | 16 STORE_FAST 0 (i) 58 | 59 | 3 19 JUMP_ABSOLUTE 13 60 | >> 22 POP_BLOCK 61 | >> 23 LOAD_CONST 0 (None) 62 | 26 RETURN_VALUE 63 | # 全局 64 | 1 0 SETUP_LOOP 20 (to 23) 65 | 3 LOAD_NAME 0 (xrange) 66 | 6 LOAD_CONST 3 (100000000) 67 | 9 CALL_FUNCTION 1 68 | 12 GET_ITER 69 | >> 13 FOR_ITER 6 (to 22) 70 | 16 STORE_NAME 1 (i) 71 | 72 | 2 19 JUMP_ABSOLUTE 13 73 | >> 22 POP_BLOCK 74 | >> 23 LOAD_CONST 2 (None) 75 | 26 RETURN_VALUE 76 | ``` 77 | 78 | 区别在于 `STORE_FAST` 比 `STORE_NAME` 要快很多。这是因为在函数里 `i` 是一个局部变量而在全局区域它是一个全局变量 79 | 80 | 用 `dis` 模块可以看字节编码,可以直接解析函数。但是要解析全局代码必须用 `compile` 内建模块 -------------------------------------------------------------------------------- /stackoverflow-about-Python/为什么用pip比用easy_install的好.md: -------------------------------------------------------------------------------- 1 | ## 为什么用pip比用easy_install的好? 2 | 3 | `pip` 是对 `easy_install` 以下方面进行了改进: 4 | 5 | * 所有的包是在安装之前就下载了,所以不会出现只安装了一部分的情况 6 | * 在终端上的输出更加友好 7 | * 对于动作的原因会进行持续的跟踪 8 | * 错误信息会非常有用 9 | * 代码简洁精悍可以很好地编程 10 | * 不必作为 egg 存档,能扁平化安装(仍然保存 egg 元数据) 11 | * 原生的支持其他版本控制系统(Git、Mercurial、Bazaar) 12 | * 卸载包 13 | * 可以简单地定义修改一系列的安装依赖等 -------------------------------------------------------------------------------- /stackoverflow-about-Python/单下划线和双下划线的含义.md: -------------------------------------------------------------------------------- 1 | ## 单下划线和双下划线的含义? 2 | 3 | ### 单下划线 4 | 5 | 在一个类中的方法或属性,用单下划线开头,就是告诉别的程序这个属性或方法是私有的。 6 | 7 | 引自 PEP-8: 8 | 9 | > 单下划线: “内部使用” 的弱指示器。比如,`from M import *` 将不会引进用单下划线开头的对象。 10 | 11 | ### 双下划线 12 | 13 | 引自 Python 文档: 14 | 15 | > 任何 `__spam` 形式(至少两个下划线开头,最多一个下划线结尾)都是代替 `_classname__spam`,其中 `classname` 是当前类的名字。 16 | 17 | ### 约定 18 | 19 | `__foo__`:Python 内部的名字,用来区别其他用户自定义的命名,以防冲突 20 | 21 | `_foo`:用来指定变量私有 22 | 23 | `__foo`:解析器将会用 `_classname__foo` 来代替这个名字,以区别和其他类相同的命名 -------------------------------------------------------------------------------- /stackoverflow-about-Python/变化的默认参数.md: -------------------------------------------------------------------------------- 1 | ## 变化的默认参数 2 | 3 | 存在一个奇怪的现象: 4 | 5 | ```python 6 | def foo(a=[]): 7 | a.append(5) 8 | return a 9 | >>> foo() 10 | [5] 11 | >>> foo() 12 | [5, 5] 13 | >>> foo() 14 | [5, 5, 5] 15 | >>> foo() 16 | [5, 5, 5, 5] 17 | >>> foo() 18 | ``` 19 | 20 | 曾经被称为动态设计缺陷,然而这个问题应当有更深层次的解释。 21 | 22 | Python 中的函数是最高等级的对象,而不仅仅是一小段代码。一个函数是一个被它自己定义而执行的对象,默认参数是一种“成员数据”,所以它们的状态和其他对象一样,会随着每一次调用而改变。 23 | 24 | 更详细的内容参考:[Python中的默认参数](http://effbot.org/zone/default-values.htm) -------------------------------------------------------------------------------- /stackoverflow-about-Python/在Android上运行Python.md: -------------------------------------------------------------------------------- 1 | ## 在 Android 上运行 Python 2 | 3 | 有一种方法,使用 Kivy。Kivy 是交互界面快速开发应用的 Python 开源库,类似于多点触控 APP 4 | 5 | Kivy 运行在 Linux、Windows、macOS、Android 和 iOS。你也可以在所有的平台上运行 Python 代码 6 | 7 | 参考:[Kivy的应用](https://play.google.com/store/apps/details?id=org.kivy.showcase) -------------------------------------------------------------------------------- /stackoverflow-about-Python/在Windows下安装pip.md: -------------------------------------------------------------------------------- 1 | ## 在Windows下安装pip 2 | 3 | ### Python3.4+ 4 | 5 | Python3.4 已经自带 pip 了,自带的包管理器中加入了 Ruby、Nodejs、Haskell、Perl、Go 等其他几乎所有的开源社区流行语言 6 | 7 | ### Python2.x 和 Python <=3.3 8 | 9 | * 官方指南,下载 `get-pip.py`,然后运行 10 | * 另一种方法:Python 包的安装器:`.msi`,可以在这个[网站](http://www.lfd.uci.edu/~gohlke/pythonlibs/)上下载 11 | 12 | ### 代理问题 13 | 14 | 可能需要 HTTP 代理,把环境变量设置为 `http_proxy` 和 `https_proxy` 15 | 16 | ```python 17 | http://proxy_url:port 18 | http://username:password@proxy_url:port 19 | ``` 20 | 21 | 如果用的是微软的 NTLM 代码,还是换一个友好一点的吧 22 | 23 | ### 找不到 `vcvarsall.bat` 24 | 25 | Pythoon 中有的模块是用 C/C++ 编写的,pip 将尝试从源码进行编译。如果没有安装或设置过 C/C++ 编译器,将会看到这个错误 26 | 27 | ```shell 28 | Error: Unable to find vcvarsall.bat 29 | ``` 30 | 31 | 可以通过安装像 MinGw 或者 VC++ 这样的编译器来解决。微软实际上已经子弟啊了一个为 Python 准备的编译器:`vcpython27` -------------------------------------------------------------------------------- /stackoverflow-about-Python/在函数里使用全局变量.md: -------------------------------------------------------------------------------- 1 | ## 在函数里使用全局变量 2 | 3 | 使用 global 关键字就可以了,例如: 4 | 5 | ```python 6 | globvar = 0 7 | 8 | def set_globvar_to_one(): 9 | global globvar # 需要用global修饰一下globvar 10 | globvar = 1 11 | 12 | def print_globvar(): 13 | print globvar # 如果要读globbar的值的话不需要用global修饰 14 | 15 | set_globvar_to_one() 16 | print_globvar() # 输出 1 17 | ``` 18 | 19 | 如果只进行读取全局变量的值,就不需要用 global 修饰 -------------------------------------------------------------------------------- /stackoverflow-about-Python/如何判断一个文件是否存在.md: -------------------------------------------------------------------------------- 1 | ## 如何判断一个文件是否存在? 2 | 3 | 不想用 `try` 语句,如何判断一个文件是否存在? 4 | 5 | 答案是: 6 | 7 | ```python 8 | import os.path 9 | os.path.isfile(file_name) 10 | ``` 11 | 12 | -------------------------------------------------------------------------------- /stackoverflow-about-Python/如何知道一个对象有一个特定的属性.md: -------------------------------------------------------------------------------- 1 | ## 如何知道一个对象有一个特定的属性? 2 | 3 | 使用 `hasattr()`: 4 | 5 | ```python 6 | if hasattr(a, 'property'): 7 | a.property 8 | ``` 9 | 10 | 在大多数实际情况下,如果一个属性有很大可能存在,那么就直接调用它或者让它引发异常,或者用 `try/except` 捕获,这种方法比 `hasattr` 快。如果这个属性很多情况下不在,或者你不确定,那么用 `hasattr` 将会比触发异常更快。 11 | 12 | -------------------------------------------------------------------------------- /stackoverflow-about-Python/如何调用外部命令.md: -------------------------------------------------------------------------------- 1 | ## 如何调用外部命令? 2 | 3 | 各种方法及各自的优缺点如下: 4 | 5 | ### os 库 6 | 7 | #### system 函数 8 | 9 | 对于运行简单的 Shell 命令而不去调用外部程序来说是非常好用的: 10 | 11 | ```python 12 | os.system("命令加参数") 13 | ``` 14 | 15 | 把命令和参数传递给你系统的 Shell 中。 16 | 17 | 用这个命令的好处在于你可以一次运行好多命令,还可以设置管道来进行重定向等。但是,这要求你手动输入空格等 Shell 字符。 18 | 19 | #### popen 函数 20 | 21 | ```python 22 | stream = os.popen("命令和参数") 23 | ``` 24 | 25 | 和 `os.stream` 差不多,但是它提供了一个链接标准输入/输出的管道,还有其他 3 个 `popen` 可以调用。可以传递字符串,也可以传递列表,列表就不用担心溢出字符了(`escaping characters` 26 | 27 | ## subprocess 库 28 | 29 | #### Popen 管道 30 | 31 | 这个 `Popen` 是打算用来替代 `os.popen` 方法的,有点复杂: 32 | 33 | ```python 34 | subprocess.Popen("echo aaa", shell=True, stdout=PIPE).stdout.read() 35 | ``` 36 | 37 | 而使用 `os.popen`: 38 | 39 | ```python 40 | os.popen("echo aaa").read() 41 | ``` 42 | 43 | 它的最大优点就是一个类代替了原来 4 个不同的 popen 44 | 45 | #### call 方法 46 | 47 | 基本用法和 Popen 类参数一致,但是它会等待命令结束后才会返回程序 48 | 49 | ```python 50 | return_code = subprocess.call("echo aaa", shell=True) 51 | ``` 52 | 53 | ### 总结 54 | 55 | * OS 模块里也有 C 语言里的 `fork/exec/spawn` 方法,但是不建议直接使用 56 | * 需要注意传递到 shell 命令一定要注意参数的安全性 57 | 58 | ```python 59 | subprocess.Popen("echo %s" % user_input, stdout=PIPE).stdout.read() 60 | ``` 61 | 62 | 如果传入 `go die && rm -rf /` 会如何。。。 -------------------------------------------------------------------------------- /stackoverflow-about-Python/如何通过函数名的字符串来调用函数.md: -------------------------------------------------------------------------------- 1 | ## 如何通过函数名的字符串来调用这个函数? 2 | 3 | 假设我们有一个模块名字为 foo,其中有一个函数为 bar,但现在只给了字符串 `"bar"`,如何通过字符串 "bar" 来调用对应的函数 `foo.bar()`? 4 | 5 | ### Solve 6 | 7 | 通过 `getattr` 方法: 8 | 9 | ```python 10 | import foo 11 | methodToCall = getattr(foo, 'bar') 12 | result = methodToCall() 13 | ``` 14 | 15 | 可以简写为: 16 | 17 | ```python 18 | result = getattr(foo, 'bar')() 19 | ``` 20 | 21 | 另外 `getattr` 可以用在实例绑定、模块级方法、类方法等 -------------------------------------------------------------------------------- /stackoverflow-about-Python/字典合并问题.md: -------------------------------------------------------------------------------- 1 | ## 字典合并问题 2 | 3 | 利用 update 方法,合并后是修改原来的字典,而不是新建一个字典作为返回值,比如: 4 | 5 | ```python 6 | >>> x = {'a':1, 'b': 2} 7 | >>> y = {'b':10, 'c': 11} 8 | >>> z = x.update(y) 9 | >>> print z 10 | None 11 | >>> x 12 | {'a': 1, 'b': 10, 'c': 11} 13 | ``` 14 | 15 | ### 解决方法一 16 | 17 | ```python 18 | z = dict(x.items() + y.items()) 19 | ``` 20 | 21 | 其中相同的键的值会被后一个字典的值覆盖 22 | 23 | 另外,如果是 Python3: 24 | 25 | ```python 26 | >>> z = dict(list(x.items()) + list(y.items())) 27 | ``` 28 | 29 | ### 解决方法二 30 | 31 | 手动复制一遍再 update 32 | 33 | ```python 34 | z = x.copy() 35 | z.update(y) 36 | ``` -------------------------------------------------------------------------------- /stackoverflow-about-Python/循环中获取索引.md: -------------------------------------------------------------------------------- 1 | ## 如何在循环中获取索引 2 | 3 | 如果像 C 或者 PHP 那样加入一个状态变量那就太不 pythonic 了 4 | 5 | 最好的选择就是用内建函数 `enumerate()` 6 | 7 | ```python 8 | for idx, val in enumerate(ints): 9 | print(idx, val) 10 | ``` 11 | 12 | -------------------------------------------------------------------------------- /stackoverflow-about-Python/快速合并列表中的列表.md: -------------------------------------------------------------------------------- 1 | ## 如何快速合并列表中的列表? 2 | 3 | 除了循环,有没有更快的方法来实现一行合并列表中的列表? 4 | 5 | 比如这样的: 6 | 7 | ```python 8 | l = [[1,2,3],[4,5,6], [7], [8,9]] 9 | reduce(lambda x,y: x.extend(y),l) 10 | ``` 11 | 12 | 当然上面这样会报错。。 13 | 14 | ### Solve 15 | 16 | 目前看来,最快的方法应该是: 17 | 18 | ```python 19 | [item for sublist in l for item in sublist] 20 | ``` 21 | 22 | 可以用 `timeit` 模块进行验证: 23 | 24 | ```python 25 | $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]' 26 | 10000 loops, best of 3: 143 usec per loop 27 | $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])' 28 | 1000 loops, best of 3: 969 usec per loop 29 | $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)' 30 | 1000 loops, best of 3: 1.1 msec per loop 31 | ``` 32 | 33 | ### 解释 34 | 35 | 当有 L 个子串的时候用 `+`,即 (`sum`)的时间复杂度是 `O(L**2)`,每次迭代的时候作为中间结果的列表的长度就会越来越长,而且前一个中间结果的所有项都会再拷贝一遍给下一个中间结果。所以当你的列表 I 含有 L 个子串,I 列表的第一项需要拷贝 `L-1` 次,而第二项要拷贝 `L-2` 次,以此类推总数为: `I * (L ** 2) / 2` 36 | 37 | 列表推导式(`list comprehension`)只是生成一个列表,每次运行只拷贝一次(从开始的地方拷贝到最终结果) -------------------------------------------------------------------------------- /stackoverflow-about-Python/怎么在终端里输出颜色.md: -------------------------------------------------------------------------------- 1 | ## 怎么在终端里输出颜色 2 | 3 | ### 方法一 4 | 5 | [Python termcolor module 模块](https://pypi.python.org/pypi/termcolor) 6 | 7 | ```python 8 | from termcolor import colored 9 | print(colored("hello", "red")) 10 | print(colored("world", "green")) 11 | ``` 12 | 13 | *** 14 | 15 | ### 方法二 16 | 17 | 这依赖于你使用哪种操作系统,最常用的方法就是输出 ANSI 转义序列: 18 | 19 | ```python 20 | class bcolors: 21 | HEADER = '\033[95m' 22 | OKBLUE = '\033[94m' 23 | OKGREEN = '\033[92m' 24 | WARNING = '\033[93m' 25 | FAIL = '\033[91m' 26 | ENDC = '\033[0m' 27 | ``` 28 | 29 | 可以这么使用上面的代码: 30 | 31 | ```python 32 | print(bcolors.WARNING + "Warning: No active frommets remain. Continue?" + bcolors.ENDC) 33 | ``` 34 | 35 | 这种方法适合 macOS、Linux 和 Windows。还有一些其他的 ANSI 代码可以设置颜色,消除光标或者其他 36 | 37 | 如果想要应用更复杂的功能,应该看看 `curses` 模块,参考:[Python Curses HowTO](https://docs.python.org/2/howto/curses.html) 38 | 39 | 如果不使用拓展的 ASCII,比如不是一个 PC,那么 `#` 或者 `@` 可能是最好的选择 40 | 41 | 如果用的是 [IBM扩展ascii字符设置](http://telecom.tbi.net/asc-ibm.html),你还可以有更多的选择。176,177,178和219是"块字符"。 42 | 43 | 一些现代的基于文本的程序,像 Swarf Fortress 显示的文本使用图像模式,而用的字体也是传统的计算机字体的图像。可以在 [Dwarf Fortress Wiki](http://dwarffortresswiki.org/DF2014:Tilesets) 找到你可以用的字符. 44 | 45 | [Text Mode Demo Contest ](http://en.wikipedia.org/wiki/Text_Mode_Demo_Contest)也有许多资料可供参考。 46 | 47 | -------------------------------------------------------------------------------- /stackoverflow-about-Python/怎么用引用来改变一个变量.md: -------------------------------------------------------------------------------- 1 | ## 怎么用引用来改变一个变量? 2 | 3 | Python 文档里,参数传递的是值还是引用并没有明确说明,现在想要通过引用来改变变量,如何实现? 4 | 5 | *** 6 | 7 | 参数是通过 assignment 来传递的,原因: 8 | 9 | * 传递的参数实际上是一个对象的引用(但是这个引用是通过值传递的) 10 | * 一些数据类型是可变的,但有一些就不是 11 | 12 | 所以: 13 | 14 | * 如果传递的是可变对象,那么就可以在方法里面改变,除非重新绑定了这个引用 15 | * 如果传递的是一个不可变对象,那么就无法实现 16 | 17 | ### 是否可变类型? 18 | 19 | * 列表-可变类型 20 | * 字符串-不可变类型 21 | 22 | ### Solve 23 | 24 | * 可以通过返回值实现 25 | * 可以建一个存放值的类,然后把它传递给函数或者用一个已有的类,比如列表: 26 | 27 | ```python 28 | def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change): 29 | new_string = something_to_do_with_the_old_string(stuff_to_change[0]) 30 | stuff_to_change[0] = new_string 31 | 32 | # 你可以像这样调用 33 | wrapper = [my_string] 34 | use_a_wrapper_to_simulate_pass_by_reference(wrapper) 35 | 36 | do_something_with(wrapper[0]) 37 | ``` 38 | 39 | 尽管看上去很笨重,但是实现需求了。。。 -------------------------------------------------------------------------------- /stackoverflow-about-Python/把列表分割成同样大小的块.md: -------------------------------------------------------------------------------- 1 | ## 把列表分割成同样大小的块 2 | 3 | 希望有个方法,比如生成器,可以实现下面的效果: 4 | 5 | ```python 6 | l = range(1, 1000) 7 | print(chunks(l, 10)) 8 | # [ [ 1..10 ], [ 11..20 ], .., [ 991..999 ] ] 9 | ``` 10 | 11 | ### Solve 12 | 13 | ```python 14 | def chunks(l, n): 15 | """ Yield successive n-sized chunks from l. 16 | """ 17 | for i in xrange(0, len(l), n): 18 | yield l[i:i+n] 19 | ``` 20 | 21 | 或者 22 | 23 | ```python 24 | tuple(l[i:i+n] for i in xrange(0, len(l), n)) 25 | ``` 26 | 27 | ### 打印效果 28 | 29 | ```python 30 | import pprint 31 | pprint.pprint(list(chunks(range(10, 75), 10))) 32 | [[10, 11, 12, 13, 14, 15, 16, 17, 18, 19], 33 | [20, 21, 22, 23, 24, 25, 26, 27, 28, 29], 34 | [30, 31, 32, 33, 34, 35, 36, 37, 38, 39], 35 | [40, 41, 42, 43, 44, 45, 46, 47, 48, 49], 36 | [50, 51, 52, 53, 54, 55, 56, 57, 58, 59], 37 | [60, 61, 62, 63, 64, 65, 66, 67, 68, 69], 38 | [70, 71, 72, 73, 74]] 39 | ``` -------------------------------------------------------------------------------- /stackoverflow-about-Python/枚举类型的使用.md: -------------------------------------------------------------------------------- 1 | ## 枚举类型的使用? 2 | 3 | PEP435 标准已经把枚举添加到 Python3.4 版本,在 PyPi 中也可以向后支持,通过: 4 | 5 | ```python 6 | pip install enum34 7 | ``` 8 | 9 | 如果下载 `enum` 没有数字将会是另一个版本 10 | 11 | ```python 12 | from enum import Enum 13 | animal = Enum("Animal", "ant bee cat dog") 14 | ``` 15 | 16 | 等价于: 17 | 18 | ```python 19 | class Animals(Enum): 20 | ant = 1 21 | bee = 2 22 | cat = 3 23 | dog = 4 24 | ``` 25 | 26 | 在更早以前,有这些方法: 27 | 28 | ```python 29 | def enum(**enums): 30 | return type('Enum', (), enums) 31 | 32 | >>> Numbers = enum(ONE=1, TWO=2, THREE='three') 33 | >>> Numbers.ONE 34 | 1 35 | >>> Numbers.TWO 36 | 2 37 | >>> Numbers.THREE 38 | 'three' 39 | ``` 40 | 41 | 或者 42 | 43 | ```python 44 | def enum(*sequential, **named): 45 | enums = dict(zip(sequential, range(len(sequential))), **named) 46 | return type('Enum', (), enums) 47 | 48 | >>> Numbers = enum('ZERO', 'ONE', 'TWO') 49 | >>> Numbers.ZERO 50 | 0 51 | >>> Numbers.ONE 52 | 1 53 | ``` 54 | 55 | 把值转换为名字: 56 | 57 | ```python 58 | def enum(*sequential, **named): 59 | enums = dict(zip(sequential, range(len(sequential))), **named) 60 | reverse = dict((value, key) for key, value in enums.iteritems()) 61 | enums['reverse_mapping'] = reverse 62 | return type('Enum', (), enums) 63 | >>> Numbers.reverse_mapping['three'] 64 | 'THREE' 65 | ``` 66 | 67 | 这样会覆盖名字下的所有东西,但是对于枚举的输出很有用。如果转换的值不存在就会抛出 KeyError 异常 -------------------------------------------------------------------------------- /stackoverflow-about-Python/根据字典值进行排序.md: -------------------------------------------------------------------------------- 1 | ## 根据字典值进行排序 2 | 3 | 对字典进行排序是不可能的,只有把字典转换成另一种方式才能排序。字典本身是无序的,但是像列表、元祖等其他类型是有序的。所以需要一个元祖列表来表示排序的字典 4 | 5 | DEMO: 6 | 7 | ```python 8 | import operator 9 | x = {1: 2, 3: 4, 4:3, 2:1, 0:0} 10 | sorted_x = sorted(x.items(), key=operator.itemgetter(1)) 11 | ``` 12 | 13 | 也可以: 14 | 15 | ```python 16 | sorted(d.items(), key=lambda x: x[1]) 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /stackoverflow-about-Python/检查列表为空的最好办法.md: -------------------------------------------------------------------------------- 1 | ## 检查列表为空的最好办法 2 | 3 | 用隐藏的空列表的布尔值才是最 Pythonic 的方法: 4 | 5 | ```python 6 | if not a: 7 | print("list a is empty") 8 | ``` 9 | 10 | 虽然我自己一般用 `len(a) == 0` -------------------------------------------------------------------------------- /stackoverflow-about-Python/检查文件夹是否存在的操作.md: -------------------------------------------------------------------------------- 1 | ## 检查文件夹是否存在的操作 2 | 3 | 方法一: 4 | 5 | ```python 6 | filename = "/my/directory/filename.txt" 7 | dir = os.path.dirname(filename) 8 | 9 | try: 10 | os.stat(dir) 11 | except: 12 | os.mkdir(dir) 13 | 14 | f = file(filename) 15 | ``` 16 | 17 | 方法二: 18 | 19 | ```python 20 | def ensure_dir(f): 21 | d = os.path.dirname(f) 22 | if not os.path.exists(d): 23 | os.makedirs(d) 24 | ``` 25 | 26 | 【注意】,如果在调用 `os.path.exists` 和 `os.makedirs` 之间被创建了,将会出现一个 `OSError`。然而捕获 `OSError` 并不能很好地解决这个问题,因为它将会忽略磁盘空间不足,没有足够权限等一些其他造成文件创建失败的因素 27 | 28 | 一个做法是捕获 OSError 异常并检查返回的错误代码 29 | 30 | 方法三: 31 | 32 | ```python 33 | os.makedirs(self.path_dir, exist_ok=True) 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /stackoverflow-about-Python/类里的静态变量.md: -------------------------------------------------------------------------------- 1 | ## 类里的静态变量 2 | 3 | 变量是在类定义时声明的,不是在类方法或静态变量中: 4 | 5 | ```python 6 | >>> class MyClass: 7 | ... i = 3 8 | ... 9 | >>> MyClass.i 10 | 3 11 | ``` 12 | 13 | 注意变量 i 是类级别的,所以它和所有实例的 i 变量是不一样的,比如: 14 | 15 | ```python 16 | >>> m = MyClass() 17 | >>> m.i = 4 18 | >>> MyClass.i, m.i 19 | >>> (3, 4) 20 | ``` 21 | 22 | 这与 C++ 以及 Java 不一样,但是和 C# 相同,就是静态成员不能被实例所引用 -------------------------------------------------------------------------------- /stackoverflow-about-Python/装饰器classmethod和staticmethod的区别.md: -------------------------------------------------------------------------------- 1 | ## 装饰器classmethod和staticmethod的区别 2 | 3 | 一个对象实体调用方法,隐藏了传递的第一个参数 `self`: 4 | 5 | ```python 6 | a.foo(1) 7 | ``` 8 | 9 | 如果方法是用 `classmethods` 装饰,那么被隐藏的第一个参数是对象的类而不是 `self`: 10 | 11 | ```python 12 | a.class_foo(1) 13 | ``` 14 | 15 | 也可以用类调用,一般被装饰为 `classmethod` 是希望用类来调用,而不是实例来调用 16 | 17 | 用 `staticmethods` 装饰,不管传递给第一个参数是 `self` 还是 `cls`,表现都一样,静态方法被用来组织类之间有逻辑关系的函数 18 | 19 | 静态方法就是一个普通方法,一个不带参数绑定的方法 20 | 21 | -------------------------------------------------------------------------------- /剑指 Offer 编程题/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 本文件保存练习剑指 Offer 时的相关代码及笔记 3 | 4 | # 题目练习链接 5 | [牛客网](http://www.nowcoder.com/ta/coding-interviews?page=) -------------------------------------------------------------------------------- /剑指 Offer 编程题/二维数组中的查找/python_solve.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | Python 解决二维数组中的查找问题 6 | """ 7 | 8 | __author__ = '__L1n__w@tch' 9 | 10 | 11 | class Solution: 12 | # array 二维列表 13 | @classmethod 14 | def Find(cls, array, target): 15 | # write code here 16 | row = len(array) 17 | column = len(array[0]) 18 | 19 | if row > 0 and column > 0: 20 | x, y = 0, column - 1 # 从右上角第一个数字开始找 21 | 22 | while 0 <= x < row and 0 <= y < column: 23 | if array[x][y] == target: 24 | return True 25 | elif array[x][y] > target: # 说明当前列不会有这个数了 26 | y -= 1 27 | elif array[x][y] < target: # 说明当前行不会有这个数了 28 | x += 1 29 | return False 30 | 31 | 32 | if __name__ == "__main__": 33 | solution = Solution() 34 | array = [[]] 35 | print(solution.Find(array, 9)) 36 | -------------------------------------------------------------------------------- /剑指 Offer 编程题/二维数组中的查找/readme.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 3 | 4 | # 思路解释 5 | 从右上角开始查找, 如果大于右上角的数, 说明当前列不可能存在这个数; 如果小于右上角的数, 说明当前行不可能存在这个数. 6 | 7 | # 条件限制 8 | 时间限制:1秒 9 | 10 | 空间限制:32768K 11 | 12 | # Python 版本最终提交 13 | ```python 14 | # -*- coding:utf-8 -*- 15 | class Solution: 16 | # array 二维列表 17 | def Find(self, array, target): 18 | # write code here 19 | row = len(array) 20 | column = len(array[0]) 21 | 22 | if row > 0 and column > 0: 23 | x, y = 0, column - 1 # 从右上角第一个数字开始找 24 | 25 | while 0 <= x < row and 0 <= y < column: 26 | if array[x][y] == target: 27 | return True 28 | elif array[x][y] > target: # 说明当前列不会有这个数了 29 | y -= 1 30 | elif array[x][y] < target: # 说明当前行不会有这个数了 31 | x += 1 32 | return False 33 | ``` 34 | 35 | # C/C++ 版本最终提交 36 | ```c++ 37 | class Solution { 38 | public: 39 | bool Find(vector > array, int target) { 40 | int row = array.size(); 41 | int column = array[0].size(); 42 | 43 | if (row > 0 && column > 0) { 44 | int x, y; 45 | x = 0, y = column - 1; 46 | while (x < row && y >= 0) { 47 | if (array[x][y] == target) { 48 | return true; 49 | } 50 | else if (array[x][y] > target) { 51 | --y; 52 | } 53 | else { 54 | ++x; 55 | } 56 | } 57 | } 58 | 59 | return false; 60 | } 61 | }; 62 | ``` -------------------------------------------------------------------------------- /剑指 Offer 编程题/二维数组中的查找/unittest_solve.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 测试自己写的答案是否正确 6 | """ 7 | import random 8 | import unittest 9 | from python_solve import Solution 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | class TestSolution(unittest.TestCase): 15 | def test_solution(self): 16 | for i in range(33): 17 | array, max_number = self.create_array() 18 | target = array[random.randint(0, len(array) - 1)][random.randint(0, len(array[0]) - 1)] 19 | self.assertTrue(Solution.Find(array, target)) 20 | self.assertFalse(Solution.Find(array, max_number + random.randint(1, max_number))) 21 | 22 | def create_array(self): 23 | """ 24 | 返回一个符合要求的二维数组以及该数组中的最大数字 25 | :return: 26 | """ 27 | rows = random.randint(1, 33) 28 | columns = random.randint(1, 55) 29 | array = list() 30 | max_number = 0 31 | 32 | for row in range(rows): 33 | column_list = list() 34 | for column in range(columns): 35 | max_number += 1 36 | column_list.append(max_number) 37 | 38 | array.append(column_list) 39 | return array, max_number 40 | 41 | 42 | if __name__ == "__main__": 43 | pass 44 | -------------------------------------------------------------------------------- /剑指 Offer 编程题/从尾到头打印链表/python_solve.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 输入一个链表,从尾到头打印链表每个节点的值。 6 | 7 | 输入为链表的表头 8 | 9 | 输出为需要打印的“新链表”的表头 10 | """ 11 | 12 | __author__ = '__L1n__w@tch' 13 | 14 | 15 | class ListNode: 16 | def __init__(self, x, next): 17 | self.val = x 18 | self.next = next 19 | 20 | 21 | class Solution: 22 | # 返回从尾部到头部的列表值序列,例如[1,2,3] 23 | def printListFromTailToHead(self, listNode): 24 | # write code here 25 | res = [] 26 | 27 | if listNode: 28 | res.insert(0, listNode.val) # 注意插入的是数值而不是整个对象 29 | while listNode.next: 30 | res.insert(0, listNode.next.val) 31 | listNode = listNode.next 32 | 33 | return res 34 | 35 | 36 | if __name__ == "__main__": 37 | listNode = ListNode(67, ListNode(0, ListNode(24, ListNode(58, None)))) 38 | solution = Solution() 39 | for each in solution.printListFromTailToHead(listNode): 40 | print(each) 41 | -------------------------------------------------------------------------------- /剑指 Offer 编程题/从尾到头打印链表/readme.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 输入一个链表,从尾到头打印链表每个节点的值。 3 | 4 | 输入描述: 5 | 6 | 输入为链表的表头 7 | 8 | 输出描述: 9 | 10 | 输出为需要打印的“新链表”的表头 11 | 12 | # Python 版本提交 13 | ```python 14 | class Solution: 15 | # 返回从尾部到头部的列表值序列,例如[1,2,3] 16 | def printListFromTailToHead(self, listNode): 17 | # write code here 18 | res = list() 19 | 20 | if listNode: 21 | res.insert(0, listNode.val) # 注意插入的是数值而不是整个对象 22 | while listNode.next: 23 | res.insert(0, listNode.next.val) 24 | listNode = listNode.next 25 | 26 | return res 27 | ``` 28 | 29 | # C/C++ 版本提交 30 | 思路跟 Python 版本一样 31 | 32 | ```c++ 33 | class Solution { 34 | public: 35 | vector printListFromTailToHead(struct ListNode *head) 36 | { 37 | vector result; 38 | 39 | if (head != NULL) 40 | { 41 | result.insert(result.begin(), head->val); 42 | while (head->next != NULL) 43 | { 44 | result.insert(result.begin(), head->next->val); 45 | head = head->next; 46 | } 47 | } 48 | return result; 49 | } 50 | }; 51 | ``` -------------------------------------------------------------------------------- /剑指 Offer 编程题/旋转数组的最小数字/readme.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 3 | 4 | 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。 5 | 6 | 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 7 | 8 | NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。 9 | 10 | # Python 版本最终提交 11 | 看别人的 C/C++ 答案那么长, 结果 Python 就一行, 果然还是得自己用 C 重写 12 | 13 | ```python 14 | class Solution: 15 | def minNumberInRotateArray(self, rotateArray): 16 | # write code here 17 | return min(rotateArray) 18 | ``` 19 | 20 | # C/C++ 版本最终提交 21 | 根据二分查找改编的, 思路是参考剑指 Offer 里给的 22 | 23 | ``` 24 | class Solution { 25 | public: 26 | int minNumberInRotateArray(vector rotateArray) 27 | { 28 | if (rotateArray.size() > 0) 29 | { 30 | int low, high, middle; 31 | low = 0; 32 | high = rotateArray.size() - 1; 33 | middle = low; 34 | 35 | // 结束条件 36 | while (rotateArray[low] >= rotateArray[high]) 37 | { 38 | // 结束条件 39 | if (high - low == 1) 40 | { 41 | middle = high; 42 | break; 43 | } 44 | 45 | // 求取中间的索引值 46 | middle = (low + high) / 2; 47 | 48 | // 判断中间值的大小, 知道它是前面的递增序列还是后面的递增序列 49 | if (rotateArray[middle] <= rotateArray[high]) 50 | { 51 | high = middle; 52 | } 53 | else if (rotateArray[middle] >= rotateArray[low]) 54 | { 55 | low = middle; 56 | } 57 | } 58 | 59 | return rotateArray[middle]; 60 | } 61 | return 0; 62 | } 63 | }; 64 | ``` -------------------------------------------------------------------------------- /剑指 Offer 编程题/替换空格/readme.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。 3 | 4 | # 思路 5 | * Python: 直接 replace() 方法就行了.... 6 | * C/C++: 剑指 Offer 给出了两种方法, 一种是 O(n^2), 从头遍历, 遇到空格就进行替换操作, 同时把其余字符往后移动; 另一种方法是先遍历一遍, 知道有几个空格, 接着准备两个指针及一个数组, 指针分别指向原始字符串以及数组的末尾, 然后从后头开始遍历, 直至两个指针相遇 7 | 8 | # Python 版本最终提交 9 | 感觉跟作弊一样的 Python: 10 | 11 | ```python 12 | # -*- coding:utf-8 -*- 13 | class Solution: 14 | # s 源字符串 15 | def replaceSpace(self, s): 16 | # write code here 17 | return s.replace(" ", "%20") 18 | ``` 19 | 20 | # C/C++ 版本最终提交 21 | 注意对 length 参数的理解, 还有这里返回结果是直接修改 str 而不是重新申请一段内存空间 22 | 23 | ```c++ 24 | //length为牛客系统规定字符串输出的最大长度,固定为一个常数 25 | class Solution { 26 | public: 27 | void replaceSpace(char *str, int length) 28 | { 29 | // 这其实可以忽略 30 | if (str == NULL || length < 0) 31 | { 32 | return; 33 | } 34 | 35 | // 遍历一遍数一下有多少个空格 36 | int space_numbers = 0; 37 | int i = 0; 38 | while (str[i] != '\0') // 注意不能数 length, 否则会越界 39 | { 40 | if (str[i++] == ' ') 41 | { 42 | ++space_numbers; 43 | } 44 | } 45 | 46 | // 计算替换后的长度 47 | int raw_length = strlen(str); 48 | int after_replace_length = raw_length + space_numbers * 2; 49 | 50 | // 定义指针 51 | int point_to_raw, point_to_new; 52 | point_to_new = after_replace_length; 53 | point_to_raw = raw_length; 54 | 55 | // while 循环遍历, 条件是两个索引值相等 56 | // while 结构体实现替换操作 57 | while (point_to_new != point_to_raw) 58 | { 59 | if (str[point_to_raw] != ' ') 60 | { 61 | str[point_to_new] = str[point_to_raw]; 62 | --point_to_new; 63 | } 64 | else 65 | { 66 | str[point_to_new] = '0'; 67 | str[point_to_new - 1] = '2'; 68 | str[point_to_new - 2] = '%'; 69 | point_to_new -= 3; 70 | } 71 | --point_to_raw; 72 | } 73 | 74 | } 75 | }; 76 | ``` 77 | -------------------------------------------------------------------------------- /剑指 Offer 编程题/用两个栈实现队列/readme.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 用两个栈来实现一个队列,完成队列的 Push 和 Pop 操作。队列中的元素为 int 类型。 3 | 4 | # Python 版本最终提交 5 | ```python 6 | class Solution: 7 | def __init__(self): 8 | self.first_stack = list() 9 | self.second_stack = list() 10 | 11 | def push(self, node): 12 | # write code here 13 | self.first_stack.append(node) 14 | 15 | def pop(self): 16 | # return xx 17 | if len(self.second_stack) <= 0: 18 | while len(self.first_stack) > 0: 19 | self.second_stack.append(self.first_stack.pop()) 20 | return self.second_stack.pop() 21 | ``` 22 | 23 | # C/C++ 版本最终提交 24 | 突然发现 C/C++ 的 pop() 方法并不返回值啊... 25 | ```c++ 26 | class Solution { 27 | public: 28 | void push(int node) 29 | { 30 | stack1.push(node); 31 | } 32 | 33 | int pop() 34 | { 35 | if (stack2.size() <= 0) 36 | { 37 | while (stack1.size() > 0) 38 | { 39 | stack2.push(stack1.top()); 40 | stack1.pop(); 41 | } 42 | } 43 | int result = stack2.top(); 44 | stack2.pop(); 45 | return result; 46 | } 47 | 48 | private: 49 | stack stack1; 50 | stack stack2; 51 | }; 52 | ``` -------------------------------------------------------------------------------- /剑指 Offer 编程题/用两个栈实现队列/two_stack_implement_queue.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 利用两个栈来实现队列 6 | """ 7 | import queue 8 | 9 | __author__ = '__L1n__w@tch' 10 | 11 | 12 | class Solution: 13 | def __init__(self): 14 | self.first_stack = list() 15 | self.second_stack = list() 16 | 17 | def push(self, node): 18 | # write code here 19 | self.first_stack.append(node) 20 | 21 | def pop(self): 22 | # return xx 23 | if len(self.second_stack) <= 0: 24 | while len(self.first_stack) > 0: 25 | self.second_stack.append(self.first_stack.pop()) 26 | return self.second_stack.pop() 27 | 28 | 29 | if __name__ == "__main__": 30 | data = [1, 2, 3, 4, 5, 6, 7, 8] 31 | q = queue.Queue() 32 | s = Solution() 33 | 34 | for each in data: 35 | q.put(each) 36 | s.push(each) 37 | 38 | for i in range(len(data)): 39 | print(s.pop(), end=" ") 40 | 41 | print("") 42 | 43 | for i in range(len(data)): 44 | print(q.get(), end=" ") 45 | -------------------------------------------------------------------------------- /剑指 Offer 编程题/重建二叉树/readme.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。 3 | 4 | # Python 最终提交 5 | ```python 6 | class Solution: 7 | # 返回构造的TreeNode根节点 8 | def reConstructBinaryTree(self, pre, tin): 9 | # write code here 10 | if pre and tin: 11 | # 找到根节点 12 | root = TreeNode(pre[0]) 13 | 14 | # 计算根节点在中序中的索引 15 | root_position_in_order = tin.index(root.val) 16 | 17 | # 计算左子树长度 18 | left_length = root_position_in_order 19 | right_length = len(tin) - root_position_in_order - 1 20 | 21 | # 比该索引值小的为左子树 22 | if left_length > 0: 23 | root.left = Solution().reConstructBinaryTree(pre[1:root_position_in_order + 1], 24 | tin[:root_position_in_order]) 25 | 26 | # 计算右子树长度 27 | if right_length > 0: 28 | # 比该索引值大的为右子树 29 | root.right = Solution().reConstructBinaryTree(pre[root_position_in_order + 1:], 30 | tin[root_position_in_order + 1:]) 31 | 32 | return root 33 | ``` 34 | 35 | # C/C++ 最终提交 36 | 思路差不多, 不过换了种实现法 37 | 38 | ```c++ 39 | class Solution { 40 | public: 41 | struct TreeNode *reConstructBinaryTree(vector pre, vector in) 42 | { 43 | if (pre.size() > 0 && in.size() > 0) 44 | { 45 | TreeNode * root = new TreeNode(pre[0]); 46 | 47 | vector::iterator root_position_in_order = find(in.begin(), in.end(), root->val); 48 | 49 | int left_length = root_position_in_order - in.begin(); 50 | 51 | 52 | root->left = Solution().reConstructBinaryTree( 53 | vector(pre.begin() + 1, pre.begin() + left_length + 1), 54 | vector(in.begin(), root_position_in_order)); 55 | root->right = Solution().reConstructBinaryTree( 56 | vector(pre.begin() + left_length + 1, pre.end()), 57 | vector(root_position_in_order + 1, in.end())); 58 | 59 | return root; 60 | } 61 | return NULL; 62 | } 63 | }; 64 | ``` -------------------------------------------------------------------------------- /剑指 Offer 编程题/重建二叉树/rebuild_binary_tree_pre_in_order.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 根据前序和中序重建二叉树 6 | """ 7 | 8 | __author__ = '__L1n__w@tch' 9 | 10 | 11 | class TreeNode: 12 | def __init__(self, x): 13 | self.val = x 14 | self.left = None 15 | self.right = None 16 | 17 | 18 | class Solution: 19 | # 返回构造的TreeNode根节点 20 | def reConstructBinaryTree(self, pre, tin): 21 | # write code here 22 | if pre and tin: 23 | # 找到根节点 24 | root = TreeNode(pre[0]) 25 | 26 | # 计算根节点在中序中的索引 27 | root_position_in_order = tin.index(root.val) 28 | 29 | # 计算左子树长度 30 | left_length = root_position_in_order 31 | right_length = len(tin) - root_position_in_order - 1 32 | 33 | # 比该索引值小的为左子树 34 | if left_length > 0: 35 | root.left = Solution().reConstructBinaryTree(pre[1:root_position_in_order + 1], 36 | tin[:root_position_in_order]) 37 | 38 | # 计算右子树长度 39 | if right_length > 0: 40 | # 比该索引值大的为右子树 41 | root.right = Solution().reConstructBinaryTree(pre[root_position_in_order + 1:], 42 | tin[root_position_in_order + 1:]) 43 | 44 | return root 45 | 46 | 47 | def post_order_print(list_node): 48 | if list_node: 49 | if list_node.left: 50 | post_order_print(list_node.left) 51 | if list_node.right: 52 | post_order_print(list_node.right) 53 | print(list_node.val, end=" ") 54 | 55 | 56 | if __name__ == "__main__": 57 | pre_order = [1, 2, 4, 7, 3, 5, 6, 8] 58 | in_order = [4, 7, 2, 1, 5, 3, 8, 6] 59 | root = Solution().reConstructBinaryTree(pre_order, in_order) 60 | post_order_print(root) 61 | -------------------------------------------------------------------------------- /安全测试开发相关面试/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 主要是整理以下几个岗位的面试经历: 4 | 5 | * 安全测试 6 | * 测试开发 7 | * 自动化测试 8 | * 业务安全 9 | * ... -------------------------------------------------------------------------------- /安全测试开发相关面试/业务安全类面试参考.md: -------------------------------------------------------------------------------- 1 | # Q&A 2 | 3 | ```shell 4 | 1、SDLC,项目有部分是 SDLC,从业务需求开始就介入,需求评审、代码审计、安全测试整个流程,安全培训,做把一些东西想要自动化,测试过程,代码审计过程; 5 | 6 | 2、负责一个业务,安全流程跟进一下,某些类型测试,自动化,推广使用 7 | 8 | 3、代码审计工具,安全扫描 app-scan,一个需求、活动、要不要上线,设计阶段就有问题,设计阶段提出问题就避免开发阶段返工开发 9 | 10 | 4、功能测试有没有接触过 11 | 12 | 5、IPS/WAF、二进制、内网渗透,哪方面更擅长 13 | 14 | 6、业务安全与二进制跨度挺大,怎么解决这个问题 15 | 16 | 7、业务安全与需求相关,敏捷开发,跟进需求有没有风险,防止数据泄露相关,风险控制类的东西,业务会上一些活动 17 | 18 | 8、讲一下工作经历 19 | 20 | 9、黑链,做哪些工作 21 | 22 | 10、判断黑链正则,自动化脚本的内容 23 | 24 | 11、主要语言是什么 25 | 26 | 12、IPS/WAF 测试效果 27 | 28 | 13、黑链工作,是负责收集数据 29 | 30 | 14、漏洞规则库,也是这种类型,写过这方面的正则吗 31 | 32 | 15、攻击 poc 是自己写的 33 | 34 | 16、SQL 注入怎么生成有效 poc 产生绕过规则 35 | 36 | 17、fuzz 负责哪一部分 37 | 38 | 18、漏洞挖掘,实战经验 39 | 40 | 19、SRC 授权,漏洞挖掘经验 41 | 42 | 20、CTF 类型,主要擅长哪方面 43 | 44 | 21、WEB 这块,业务上的问题 WEB 页面、小程序,API 调用,偏向于 WEB 这块 45 | 46 | 22、反序列化漏洞 47 | 48 | 23、Java 能力怎么样 49 | 50 | 24、WEB-XSS 过滤哪些字符 51 | 52 | 25、比较熟悉哪一块,WEB 类的 53 | 54 | 26、伪造 Cookie 怎么弄的 55 | 56 | 27、文件包含,getshell,场景,常见题目 57 | 58 | 28、二进制,绕过病毒,杀毒软件 59 | 60 | 29、分析 EXE、ELF 61 | 62 | 30、给个新的病毒,分析行为,别人没分析过的 63 | 64 | 31、分析找到 CC2C 后门的 65 | 66 | 32、方向规划 67 | 68 | 33、倾向于手工测试、自动化测试【攻击】 69 | 70 | 34、burpsuite 用过吗 71 | 72 | 35、burpsuite 写插件 73 | 74 | 36、SDLC 不做测试,不做评审,转做大数据方面安全研究,数据方面的安全研究 75 | 76 | 37、蓝军,WEB、内网渗透 77 | 78 | 38、利用已有的安全的知识,去实现一系列自动化测试 79 | 80 | 39、自动化挖掘,SRC 81 | 82 | 40、离开的原因,薪资 83 | 84 | 41、有什么问题 85 | 86 | ``` -------------------------------------------------------------------------------- /安全测试开发相关面试/安全测试类面试参考.md: -------------------------------------------------------------------------------- 1 | # Q&A 2 | 3 | 安全、测试方案等多个维度 4 | 5 | ```shell 6 | 1、自我介绍 7 | 不要有太多口语化的词汇,比如老是说【然后】 8 | 9 | 2、测试方案的介绍 10 | 【需求分析】 -> 跟干系人沟通,不同产品线不同层次的干系人有不同的需求,做到什么目标要覆盖到哪些测试面; 11 | 【攻击手段梳理】 -> 站在攻击者的角度,搜集攻击场景,比如说 IPS/WAF 漏洞攻击,WEB 就经常分为 SQL 注入、XSS、CSRF 之类的;然后黑链的话,就分为 JS 挂链,黑词替换,词本身形态变换之类的;文件杀毒的话,几个维度,比如传播方式,或者病毒种类,蠕虫、木马、勒索、挖矿之类的; 12 | 【测试项梳理】 -> 整合需求分析、整合攻击手段,用一些测试项设计的方法,测试项设计方法比如:需求分析、场景分析、逻辑分析、关联分析; 13 | 【测试点梳理】 -> 也是用测试点设计方法来生成,比如说,等价类、边界值、正反对比、业务逻辑等等 14 | 【测试案例的编写以及自动化】 -> 包括了样本建设、测试自动化,竞品分析之类的 15 | 【效果改进】 -> 开评审会,讨论测出来的效果,哪方面是劣势,哪方面需要优先改,包括产品本身,测试优化,以及测试输出(PK 样本,竞标打法等) 16 | 【测试结果归档】 -> 测出来的各种打法以及对应的 PK 样本,提供给一线用的之类的东西;测试数据测试结果啥的,都要归档整理吗 17 | 18 | 3、通用方案只在 AI 里面进行了测试吗 19 | 这套方案经过多个安全项目测试之后整合出来的一套方案,安全项目测试里面包括了 AI 和非 AI 都有涉及到,理论上方案是通用各个安全方向的,只是不同方向的细节需要考虑一下 20 | 21 | 4、文件大小,测试项 22 | 有几个维度产生测试点,比如说产品线,对 2MB 可以作为一个临界值,比如说场景,PE 头 224 字节,可能刚好少了那么 1 个字节引擎就判黑了,224 也可以作为一个边界值 23 | 24 | 5、测试点,自动化测试脚本可以测试任何产品吗 25 | 分俩块,一个是测试数据,一个是测试脚本,测试数据是通用的,就通过脚本,包括爬虫脚本/文件生成脚本之类的,生成出来的数据;还有一个测试脚本,针对不同形态产品的自动化测试 26 | 27 | 6、腾讯电脑管家企业版和个人版的竞品分析 28 | 公司对标产品线干系人讨论,比如说防火墙对标,AF部门,友商是华为防火墙、360防火墙之类的,就讨论比如说病毒名的显示、文件大小的支持、企业版个人版之类的 29 | 30 | 7、有跟腾讯沟通吗? 31 | 做竞品分析怕泄露样本之类的 32 | 33 | 8、页面安全产品的测试? 34 | 测的安全产品是单独的模块,抽离出来测试了,提高测试效率;然后页面端的测试就做一些偏功能性的测试,比如说病毒名显示是否正常,黑产溯源能不能准确判定出黑词之类的 35 | 36 | 9、核心,各种类型的安全测试 37 | 主要是安全产品做自动化测试,以及后面研究不同安全方向设计测试方案并落地同时自动化之类的 38 | 39 | 10、通用测试方案,学习阶段,学校阶段,能够输出类似的产出吗,工作跟学校最大的区别 40 | 工作思维,学生思维:工作中讲究尽可能快的把时间做好做成,学生可能就是给你一段时间,你慢慢研究,这段时间内尽可能做完这件事情然后反馈 41 | 学校里面可以产生类似的报告,各种研究报告,就给你一个攻击场景,中间人攻击场景,然后你怎么复现之类的 42 | 43 | 11、工作中尽快出成果,是怎么确保的 44 | 接到任务后分清核心需求,然后排计划,工作量小就先做出成果,再来看怎么改进;工作量大就先选方案,快速出小成果,根据小成果来进一步做决策 45 | 46 | 12、这个快速 DEMO 的模式,是怎么学到的 47 | 导师传授了一部分经验,说是要快速产生价值; 48 | 49 | 13、AI 引擎,测试需求,怎么完成需求分析,做什么测试 50 | 通用的测试方案里面 51 | 52 | 14、所有安全类测试产品都总结到这个测试方案里面 53 | 不同的安全方向,测试产品主要是有需求不同,自动化测试方法不同啊 54 | 55 | 15、杀毒引擎是 AI 杀毒引擎 56 | SAVE-AI 引擎 + 小红伞黑盒引擎 57 | 58 | 16、不同于通用测试方案的测试点 59 | 每个安全方向或者每个测试产品都有不同的,就比如 blablabla 60 | 61 | 17、AI 有什么特别的地方,测试项和测试点 62 | AI 是通过学习生成的引擎,还有泛化的概念,测试的时候得避免用学习过的数据来测试,然后 AI 引擎具有不确定性,比如俩恶意文件,利用同样的漏洞 永恒之蓝,一个能检出一个没法检出 63 | 64 | 18、测试数据是怎么选择的 65 | 避免学习过的数据,测试项整理不同维度,然后筛选 66 | 67 | 19、没学习过的数据,怎么弄到 68 | 避开爬取的网站,然后自己生成,md5 清单区别,测试项区分等 69 | 70 | 20、结果改进,建议,优先级 71 | (1)安全事件;(2)公司战略;(3)CVE 编号高中低威胁程度;(4)客户反馈; 72 | 73 | 21、规则制定,怎么知道有这些东西 74 | 摸索,整合零散的,得到的,然后落地,看效果,效果不错就继续使用 75 | 76 | 22、调研,论文,博客园,安全测试方案 77 | 各种网站各种论坛搜索 78 | 79 | 23、CTF 比赛,比赛的内容,如何去做的 80 | 基于刷题经验积累 81 | 82 | 24、CTF 经验是哪里来的 83 | 刷题,大学期间,还有自己业余刷题 84 | 85 | 25、在学校的时候没有参加过正式的 CTF 比赛吗 86 | 有,比较少 87 | 88 | 26、学校有自己的战队 89 | 有,但是没去 90 | 91 | 27、上完本科之后没继续研究,钻研信息安全 92 | 以工作优先,工作有涉及会研究,工作没涉及看自己私下需求了 93 | 94 | 28、学校是自己准备东西上去讲的 95 | 翻转课堂 96 | 97 | 29、老师的作用是啥 98 | 搜集资料,提供 99 | 100 | 30、爬虫的了解 101 | 简单的网站,requests 库爬取,复杂一点的,selenium 库 102 | 103 | 31、滑动检测之类的,反爬技术,怎么解决 104 | 基本思路就是,识别出【目标区域】、然后拟人拖动到对应区域,https://juejin.im/entry/5b9b995cf265da0ac1390530 105 | 106 | 32、滑动的那个,验证过一次,之后还会再次校验 107 | 不同网站反爬技术不同,所以需要区别对待 108 | 109 | 33、安全测试对本身的安全性要求也比较高 110 | 安全测试俩目标:产品本身的安全性以及、安全产品的安全能力 111 | 112 | 34、单元测试 113 | django-test 框架,unittest 框架,mock 模块,selenium 框架,无界面框架比如(PhantomJS)之类的 114 | 115 | 35、网站源码,情况 116 | 放到 github 上了 117 | 118 | 36、单测,怎么实现的 119 | unittest 库,用断言来判断结果是不是正确的,然后可以用 mock 模拟一下中间函数的调用 120 | 121 | 37、当导师带徒弟 122 | 快速产生工作价值 123 | 124 | 38、怎么判断哪些东西比较重要 125 | (1)公司战略;(2)BOSS关注点;(3)市场价值 126 | 127 | 39、2 月离职现在回 128 | 很多个因素 129 | 130 | 40、个人规划是什么样的 131 | 测试开发 132 | 133 | 41、你还有什么想问的 134 | 想提升测试能力,想问公司测试技术属于大概什么水平 135 | ``` -------------------------------------------------------------------------------- /安全测试开发相关面试/测试开发类面试参考.md: -------------------------------------------------------------------------------- 1 | # Q&A 2 | 3 | ## 笔试 4 | 5 | ```shell 6 | 1、列表生成式,去重,排序 7 | 8 | 2、SQL 语句,多个表联合查询 9 | SELECT * FROM 10 | 11 | 3、ANR 12 | https://baike.baidu.com/item/ANR 13 | 14 | 4、KNN 算法 15 | https://baike.baidu.com/item/%E9%82%BB%E8%BF%91%E7%AE%97%E6%B3%95/1151153?fromtitle=Knn&fromid=3479559 16 | 17 | 5、激活函数 18 | https://blog.csdn.net/qrlhl/article/details/60883604 19 | 20 | 6、装饰器作用,使用,如何编写 21 | 22 | 7、单线程模型,Manager、Manager_Queue,Looper 啥的 23 | https://blog.csdn.net/Skypine_Lee/article/details/7692693 24 | 25 | 8、private、protected、publice 区别 26 | 27 | 9、常用 Linux/adb 命令 28 | ``` 29 | 30 | ## 面试 31 | 32 | ```shell 33 | 1、先做个自我介绍 34 | 35 | 2、安全测试应用到手机的话会有什么测试方法 36 | 37 | 3、有没有针对手机做过这种测试 38 | 39 | 4、如果特意针对手机端要怎么做 40 | 41 | 5、如果自动化实施 42 | 43 | 6、有对 Linux 系统做安全测试 44 | 45 | 7、自动化经验主要集中在哪一块 46 | 47 | 8、哪一块做得比较好的,是有可扩展性 48 | 49 | 9、了解过框架的源码,工作原理 50 | 51 | 10、网站是怎么做的,具体讲一下 52 | 53 | 11、硬件开发的经历 54 | 55 | 12、安全方面的自动化流程,相关的业务介绍 56 | 57 | 13、做的工具在安全测试那一套 58 | 59 | 14、这套自动化逻辑应该放到哪个阶段去用,效率最大化,价值体现 60 | 61 | 15、按想法,自动化框架,会做成什么样子 62 | 63 | 16、安全测试部门,主要内容 64 | 65 | 17、自动化测试工程师要什么阶段接入 66 | 67 | 18、现在行业现状,测试都是什么阶段接入,最好应该是什么接入 68 | 69 | 19、系统测试,内容,正常来说会不会有大量的自动化接入,再开放到系统测试,也会有测试工程师,自动化工程师 70 | 71 | 20、个人的规划是怎么样的 72 | 73 | 21、理解的测试开发是做什么的 74 | 75 | 22、自动化生成自动化案例的方法 76 | 77 | 23、前端测试,UI 的稳定性是怎么保证,维护成本 78 | 79 | 24、WEB 端和手机 APP,兼容性怎么保证的,遍历测试,弹窗 80 | 81 | 25、怎么保证自动化流程能够跑通,自动化的维护成本 82 | 83 | 26、有没有好的方法 84 | 85 | 27、异常弹窗,正常提示,系统测试 86 | 87 | 28、迁移工作量 88 | 89 | 29、测微信、QQ,突然有个异常弹窗,大量的处理这种场景,处理这些异常的东西 90 | 91 | 30、自动化,脚本执行的成功率,跑的效果达不到预期 92 | 93 | 31、前沿的测试领域有什么可以发挥的地方 94 | 95 | 32、短期内,进来的话期望的工作,具体一点 96 | 97 | 33、有什么其它问题 98 | 99 | 34、airtest 是基于谷歌原生的测试框架做的 100 | 101 | 35、进来之后的工作内容 102 | 103 | 36、对工作状态,不断换新项目 104 | 105 | 37、离职原因 106 | 107 | 38、下一份工作的期待 108 | 109 | 39、对加班怎么看 110 | 111 | 40、大学的大部分时间都处理自己的事情,加班是处理公司的事情,会占用个人的时间,怎么看? 112 | 113 | 41、996 怎么看 114 | ``` -------------------------------------------------------------------------------- /安全测试开发相关面试/测试开发类面试参考2.md: -------------------------------------------------------------------------------- 1 | # Q&A 2 | 3 | ```shell 4 | 1、电话面试介绍 5 | 6 | 2、除 Python 外其他语言的情况 7 | 8 | 3、测试开发分前端、后台,后台用的 node.js 9 | 10 | 4、讲一下项目的测试,以及内容介绍 11 | 12 | 5、并发上的改动 13 | 14 | 6、网站,单元测试覆盖率,80%,觉得这个覆盖率够不够 15 | 16 | 7、假设,测试开发的项目,哈希碰撞,测不到的分支,测不到的,这种问题,要怎么处理 17 | 18 | 8、C++ 的程序,类里面的私有函数,对外的接口只有 public 公有函数,私有函数 mock 不到的 19 | 20 | 9、不是简单的哈希碰撞还是特有格式哈希碰撞 21 | 22 | 10、代码实在覆盖不到的,想什么办法去保证这个正确 23 | 24 | 11、大概的规划 25 | 26 | 12、2 月份离职 27 | 28 | 13、语言学习需要多久 29 | 30 | 14、C++、Java、node.js、Python 31 | 32 | 15、管家,更喜欢什么项目一些 33 | 34 | 16、测试开发,30% 做业务的测试,70% 时间做工具开发,项目紧急可能会在业务上多做一些 35 | 36 | 17、不做业务的话不知道用什么工具去优化测试效率 37 | 38 | ``` -------------------------------------------------------------------------------- /安全测试开发相关面试/测试开发类面试参考3.md: -------------------------------------------------------------------------------- 1 | # Q&A 2 | 3 | ## 笔试题 4 | 5 | ## 一面 6 | 7 | ```shell 8 | 1、住在哪边 9 | 10 | 2、做下自我介绍 11 | 12 | 3、离开上家的原因 13 | 14 | 4、做项目自动化,详细说一下 15 | 16 | 5、多个环境切换着跑 17 | 18 | 6、不同的系统之间,怎么切换 19 | 20 | 7、淘宝下单,提交,整个流程路径如何覆盖测试,多个系统测试怎么想 21 | 22 | 8、UI 层的测试 23 | 24 | 9、硬件这块,如何去断言的 25 | 26 | 10、selenium 框架,定位元素,有没有其他方法 27 | 28 | 11、Selenium 截图(get_screenshot_as_file)、ActionChains、wait_for_element_with_id 29 | 30 | 12、断言函数,True、Contains、None、Equal、TemplateUsed 31 | 32 | 13、自动化测试案例的管理框架 33 | 34 | 14、最后自动化测试报告的形式 35 | 36 | 15、自动化框架的优缺点 37 | 38 | 16、接口自动化测试 39 | 40 | 17、接口的测试,接触过哪些协议 41 | 42 | 18、接口,加密测试,登录,加密接口测试,自动化测试 43 | 44 | 19、加密,二次处理 45 | 46 | 20、Python 考点有哪些 47 | 48 | 21、安卓相关的接触 49 | 50 | 22、下份工作的规划 51 | 52 | 23、测试领域,具体一点 53 | 54 | 24、黑盒测试 55 | 56 | 25、自动化项目的人员情况 57 | 58 | 26、有没有什么想问的 59 | 60 | ``` 61 | 62 | ## 二面 63 | 64 | ```shell 65 | 1、自我介绍 66 | 67 | 2、测试领域指的是什么 68 | 69 | 3、自动化测试框架都是自己搭建的吗 70 | 71 | 4、自动化引擎具体说明一下 72 | 73 | 5、举一些攻击的场景 74 | 75 | 6、智能家居,安全攻击 76 | 77 | 7、做安全测试的经验比较多,功能性测试能做吗 78 | 79 | 8、创新指的是什么 80 | 81 | 9、有什么要问的 82 | 83 | 10、为什么不读研 84 | 85 | ``` 86 | 87 | ## 三面 88 | 89 | ```shell 90 | 1、做过自动化测试的项目,自动化测试的框架,描述一下 91 | 92 | 2、什么叫数据驱动 93 | 94 | 3、数据驱动和关键字驱动的区别 95 | 96 | 4、关键字驱动怎么实现 97 | 98 | 5、由关键字找函数 99 | 100 | 6、如果没有 Python 的字典,字典的底层,怎么实现 101 | 102 | 7、哈希表的原理 103 | 104 | 8、结构体怎么存 105 | 106 | 9、除了哈希表,怎么实现字典 107 | 108 | 10、举例来说,什么时候用关键字的模式,什么时候用数据驱动的模式 109 | 110 | 11、概要设计,怎么设计框架 111 | 112 | 12、同一个行为,实现不同,怎么做 113 | 114 | 13、安全测试的例子 115 | 116 | 14、系统有什么安全问题,怎么发现,内网渗透流程 117 | 118 | 15、密码学了解多少 119 | 120 | 16、C 语言掌握怎么样 121 | 122 | 17、自己的兴趣,倾向 123 | 124 | 18、开发和测试之间的倾向 125 | 126 | ``` 127 | 128 | ## HR 面 129 | 130 | ```shell 131 | 1、跟面试官讨论的规划如何 132 | 133 | 2、从哪里过来的 134 | 135 | 3、专业 136 | 137 | 4、离职原因 138 | 139 | 5、同班的有多少 140 | 141 | 6、上一家公司呆的哪些部门 142 | 143 | 7、职称评定 144 | 145 | 8、做得好是因为什么 146 | 147 | 9、看公司,哪些维度排序 148 | 149 | 10、智能家居有前景 150 | 151 | 11、待遇这块,需要个参考标准 152 | 153 | 12、想问的 154 | 155 | ``` -------------------------------------------------------------------------------- /安全测试开发相关面试/测试类HR面参考.md: -------------------------------------------------------------------------------- 1 | # Q&A 2 | 3 | ```shell 4 | 1、做自我介绍 5 | 6 | 2、离职的原因 7 | 8 | 3、对工作的规划与期待 9 | 10 | 4、测试,长期规划 11 | 12 | 5、工作与生活的时间 13 | 14 | 6、工作强度,手机厂商竞争激烈,能不能接受,怎么看待 15 | 16 | 7、加班费,体现在月薪、年薪里 17 | 18 | 8、有其他的 Offer 19 | 20 | 9、为什么对本公司比较感兴趣 21 | 22 | 10、目前用的什么手机 23 | 24 | 11、过往的工作经历,最有成就感 25 | 26 | 12、做了 17 个项目 27 | 28 | 13、为什么能够比较快的产生价值,原因 29 | 30 | 14、工作过程,挫败感很强 31 | 32 | 15、能力长板短板 33 | 34 | 16、工作过程中的困难有没有遇到过 35 | 36 | 17、压力非常大 37 | 38 | 18、过往有没有经历过没有做好的,对自己有过怀疑,不自信的 39 | 40 | 19、用三个词来形容一下自己 41 | 42 | 20、涉猎广,深度不够,怎么改善 43 | 44 | 21、领导怎么评价 45 | 46 | 22、同事怎么评价 47 | 48 | 23、最大的优点,最大的缺点 49 | 50 | 24、做好测试需要哪些因素 51 | 52 | 25、目前,薪资情况 53 | 54 | 26、找工作的薪资需求,自己满意的薪资情况 55 | 56 | 27、做测试工作的过程,有产品要上市了,前一天或者前一周突然发现了一个很大的漏洞和 BUG 57 | 58 | 28、家里情况,回去的情况 59 | 60 | 29、怎么看待给的岗位 61 | 62 | 30、会考虑哪些方面,了解的维度 63 | 64 | 31、有没有什么问题要问的 65 | 66 | ``` -------------------------------------------------------------------------------- /安全测试开发相关面试/测试类综合面试参考.md: -------------------------------------------------------------------------------- 1 | # Q&A 2 | 3 | ```shell 4 | 1、具体什么原因从上家离职 5 | 6 | 2、16 年就开始工作了吗 7 | 8 | 3、分享下家庭的情况 9 | 10 | 4、老家在哪里 11 | 12 | 5、父母在深圳还是在哪 13 | 14 | 6、自动化测试的经历讲一下 15 | 16 | 7、手机端相关的经验 17 | 18 | 8、最大的优势 19 | 20 | 9、对安全比较感兴趣 21 | 22 | 10、性格 23 | 24 | 11、...声音太小了 25 | ``` -------------------------------------------------------------------------------- /深信服_sangfor_相关/readme.md: -------------------------------------------------------------------------------- 1 | # 深信服 2 | 3 | 主要是自己在深信服工作期间接触到的知识点整理 4 | 5 | ## 清单 6 | 7 | * 软件测试面试题【作为面试官,拿到的部分问题】 8 | * 比赛的题目【智安全杯、acm 之类的,部分题目】 9 | * 期间整理的培训学习资料啥 10 | 11 | ## 备注 12 | 13 | 由于安全性考虑,部分涉密的,需要过滤一下 -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/A.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 #默认编码格式为utf-8 2 | import sys 3 | 4 | def solve(question_list, t): 5 | sum_all = 0 6 | for each in question_list: 7 | p, s = each.split(" ") 8 | if s == "0": 9 | # no 10 | sum_all += int(p) * 2 11 | else: 12 | sum_all += int(p) * t 13 | 14 | print("{}".format(sum_all)) 15 | 16 | 17 | if __name__ == "__main__": 18 | with open("test_A.txt", "r") as f: 19 | sys.stdin = f 20 | 21 | while True: 22 | try: 23 | n = input() 24 | if n == 0: 25 | break 26 | else: 27 | question = list() 28 | for i in range(n): 29 | question.append(raw_input().strip()) 30 | t = input() 31 | solve(question, t) 32 | except EOFError: 33 | break 34 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | 4 | def change_hour(hour, limit): 5 | hour = str(hour) 6 | 7 | if limit == 12: 8 | # 改变 0 9 | for each in range(0, 10): 10 | try_change = "{}{}".format(each, hour[1]) 11 | if 1 <= int(try_change) <= limit: 12 | return try_change 13 | 14 | # 改变 1 15 | for each in range(1, 10): 16 | try_change = "{}{}".format(hour[0], each) 17 | if 1 <= int(try_change) <= limit: 18 | return try_change 19 | else: 20 | # 改变 0 21 | for each in range(0, 10): 22 | try_change = "{}{}".format(each, hour[1]) 23 | if 0 <= int(try_change) < limit: 24 | return try_change 25 | 26 | # 改变 1 27 | for each in range(0, 10): 28 | try_change = "{}{}".format(hour[0], each) 29 | if 0 <= int(try_change) < limit: 30 | return try_change 31 | 32 | 33 | def change_minute(hour, minute, limit): 34 | minute = str(minute) 35 | # minute < 59 36 | # 改变 0 37 | for each in range(0, 10): 38 | try_change = "{}{}".format(each, minute[1]) 39 | if 0 <= int(try_change) <= 59: 40 | return try_change 41 | 42 | # 改变 1 43 | for each in range(0, 10): 44 | try_change = "{}{}".format(minute[0], each) 45 | if 0 <= int(try_change) <= 59: 46 | return try_change 47 | 48 | 49 | def deal_24(time): 50 | hour, minute = time.split(":") 51 | hour, minute = int(hour), int(minute) 52 | 53 | if hour < 24 and minute > 59: 54 | minute = change_minute(hour, minute, 24) 55 | elif hour < 24 and minute == 59: 56 | pass 57 | elif hour < 24 and minute < 59: 58 | pass 59 | elif hour == 24 and minute > 59: 60 | hour = 23 61 | minute = change_minute(hour, minute, 24) 62 | elif hour == 24 and 0 <= minute <= 59: 63 | hour = 23 64 | elif hour > 24 and minute > 59: 65 | hour = change_hour(hour, 24) 66 | minute = change_minute(hour, minute, 24) 67 | elif hour > 24 and minute <= 59: 68 | hour = change_hour(hour, 24) 69 | 70 | return "{}:{}".format(str(hour).zfill(2), str(minute).zfill(2)) 71 | 72 | 73 | def deal_12(time): 74 | hour, minute = time.split(":") 75 | hour, minute = int(hour), int(minute) 76 | 77 | if hour == 0 and minute > 59: 78 | hour = 1 79 | minute = change_minute(hour, minute, 12) 80 | elif hour == 0 and minute == 59: 81 | hour = 1 82 | elif hour == 0 and minute < 59: 83 | hour = 1 84 | elif 0 < hour <= 12 and minute > 59: 85 | minute = change_minute(hour, minute, 12) 86 | elif 0 < hour <= 12 and minute == 59: 87 | pass 88 | elif 0 < hour <= 12 and minute < 59: 89 | pass 90 | elif hour == 13 and minute > 59: 91 | hour = 12 92 | minute = change_minute(hour, minute, 12) 93 | elif hour == 13 and 0 <= minute <= 59: 94 | hour = 12 95 | elif hour > 13 and minute > 59: 96 | hour = change_hour(hour, 12) 97 | minute = change_minute(hour, minute, 12) 98 | elif hour > 13 and minute <= 59: 99 | hour = change_hour(hour, 12) 100 | 101 | return "{}:{}".format(str(hour).zfill(2), str(minute).zfill(2)) 102 | 103 | 104 | def solve(n, time): 105 | if n == 24: 106 | return deal_24(time) 107 | else: 108 | return deal_12(time) 109 | 110 | 111 | if __name__ == "__main__": 112 | with open("test_C.txt", "r") as f: 113 | sys.stdin = f 114 | 115 | with open("test_C_answer.txt", "w") as f1: 116 | while True: 117 | try: 118 | n = int(input()) 119 | # n = input() 120 | # time = raw_input() 121 | time = input() 122 | # print(solve(n, time)) 123 | print("{}小时,原来={},自己的答案={}".format(n, time, solve(n, time)), file=f1) 124 | except EOFError: 125 | break 126 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C_ACM/out(2).zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/L1nwatch/interview_collect/a3ec3f4bf57099cbd6acf9ba4e9797e685d5a4ce/深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C_ACM/out(2).zip -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C_ACM/right_C_answer.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/L1nwatch/interview_collect/a3ec3f4bf57099cbd6acf9ba4e9797e685d5a4ce/深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C_ACM/right_C_answer.zip -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C_ACM/sxf.cpp: -------------------------------------------------------------------------------- 1 | //题目描述 2 | //火星探险队到了一个洞穴,里面有一座桥,由石板铺就,石板上面有大写英文字母,经探索发现,只有 3 | // 4 | //标有元音字母A,E,I,O,U,Y的字母的石板是安全的,其它石板都会翻动。 5 | // 6 | //只有从桥左边位置走到桥右边位置才能算脱险。对于不是连续元音的石板,只能采用跳过去的方法。 7 | // 8 | //如下石板桥 9 | // 10 | // 11 | // 12 | //如果跳跃能力达不到4个格是无法穿越石板桥的。 13 | // 14 | //帮忙算一下探险队要安全脱险的最小跳跃能力是多少。 15 | // 16 | //输入 17 | //一个字符串只有大写英文字母。 18 | // 19 | //长度最大为100 20 | // 21 | //输出 22 | //一个整数,代表最小的跳跃能力。 23 | //样例输入 24 | //ABABBBACFEYUKOTT 25 | //AAA 26 | //样例输出 27 | //4 28 | //1 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | using namespace std; 41 | 42 | int main() 43 | { 44 | string s; 45 | int len; 46 | while(cin>>s) 47 | { 48 | int r = 1,min = 1; 49 | len = s.length(); 50 | for(int i = 0;imin) 55 | { 56 | min = r; 57 | r = 1; 58 | } 59 | else 60 | r = 1; 61 | } 62 | else 63 | { 64 | ++r; 65 | if(r>min) min = r; 66 | // cout< 44 | //#include 45 | //#include 46 | //#include 47 | //#include 48 | //#include 49 | //#include 50 | //#include 51 | //#include 52 | 53 | #include 54 | using namespace std; 55 | 56 | int main() 57 | { 58 | int n; 59 | int t; 60 | while(cin>>n && n) 61 | { 62 | long long sum = 0,temp = 0; 63 | long long p,s; 64 | for(int i = 0;i>p>>s; 67 | if(s) temp += p; 68 | else sum += p * 2; 69 | } 70 | cin>>t; 71 | sum = sum + temp * t; 72 | cout< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | int char_to_int(char a) 15 | { 16 | int result = int(a - '0'); 17 | return result; 18 | } 19 | 20 | int main() 21 | { 22 | int n; 23 | cin>>n; 24 | char a,b,c,d,p; 25 | cin>>a>>b>>p>>c>>d; 26 | 27 | int x = char_to_int(a)*10 + char_to_int(b); 28 | int y = char_to_int(c)*10 + char_to_int(d); 29 | 30 | if(n == 24) 31 | { 32 | if(x<=23 && y<=59) 33 | { 34 | cout<23 && y<=59) 37 | { 38 | cout<<0<59) 41 | { 42 | cout<23&&y>59) 45 | cout<<0<0 &&y<=59) 54 | // cout<<0<59) 56 | // cout<<0<59) 63 | cout<<1<0 && y<=59) 66 | { 67 | cout<12 && y<=59) 70 | { 71 | // cout<<0<0 && y >59) 78 | { 79 | cout<12&&y>59) 82 | { 83 | if(b == '0') 84 | cout<<1< 0: 75 | temp = right_answers.pop(0) 76 | else: 77 | break 78 | 79 | if person_answer.pop(0) in answer_of_this_blank: 80 | counts += 1 81 | 82 | return counts 83 | 84 | 85 | def solve(question_input): 86 | number_of_questions = int(question_input.pop(0)) 87 | questions, answers, is_ordered = list(), list(), list() 88 | for each_question in range(number_of_questions): 89 | questions.append(question_input.pop(0)) 90 | answers.append(question_input.pop(0)) 91 | is_ordered.append(question_input.pop(0)) 92 | 93 | judge_list = build_question_and_answer(questions, answers, is_ordered) 94 | 95 | number_of_person = int(question_input.pop(0)) 96 | results = list() 97 | for each_person in range(number_of_person): 98 | counts = 0 99 | for answer_order in range(number_of_questions): 100 | counts += right_answer_account(answer_order, question_input.pop(0), judge_list) 101 | results.append(str(counts)) 102 | 103 | return results 104 | 105 | 106 | if __name__ == "__main__": 107 | while True: 108 | try: 109 | question_input = list() 110 | 111 | n = input() 112 | question_input.append(n) 113 | for i in range(n): 114 | for j in range(3): 115 | question_input.append(raw_input()) 116 | 117 | 118 | m = input() 119 | question_input.append(m) 120 | for i in range(m): 121 | for j in range(n): 122 | question_input.append(raw_input()) 123 | 124 | for each in solve(question_input): 125 | print(each) 126 | except EOFError: 127 | break 128 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1076.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 从键盘输入一年份,判断年份是否为闰年。 7 | 8 | 输入 9 | 输入一整数,表示年份。 10 | 11 | 输出 12 | 输出判断结果。是闰年输出"Yes";不是闰年输出"No"。 13 | 14 | 样例输入 15 | 2011 16 | 样例输出 17 | No 18 | """ 19 | 20 | __author__ = '__L1n__w@tch' 21 | 22 | 23 | def is_leap(year): 24 | return year % 400 == 0 or (year % 100 != 0 and year % 4 == 0) 25 | 26 | 27 | def solve(number): 28 | if is_leap(number): 29 | return "Yes" 30 | else: 31 | return "No" 32 | 33 | 34 | if __name__ == "__main__": 35 | while True: 36 | try: 37 | num = int(input()) 38 | print solve(num) 39 | except EOFError: 40 | break 41 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1077.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 编写程序,给出一个其值不超过12345678的正整数,求出它是几位数。 7 | 8 | 输入 9 | 不超过12345678的正整数. 10 | 11 | 输出 12 | 该正整数的位数 13 | 14 | 样例输入 15 | 31888 16 | 样例输出 17 | 5 18 | """ 19 | 20 | __author__ = '__L1n__w@tch' 21 | 22 | 23 | def solve(number): 24 | return len(str(number)) 25 | 26 | 27 | if __name__ == "__main__": 28 | while True: 29 | try: 30 | num = int(input()) 31 | print solve(num) 32 | except EOFError: 33 | break 34 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1078.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 输入一个其值不大于32767的正整数,将各位数字分离出来,依次显示。 7 | 8 | 输入 9 | 不大于32767的正整数 10 | 11 | 输出 12 | 输出正整数的各位数字,各位数字间用逗号隔开,最后一位数字之后换行。 13 | 14 | 样例输入 15 | 32767 16 | 样例输出 17 | 3,2,7,6,7 18 | """ 19 | 20 | __author__ = '__L1n__w@tch' 21 | 22 | 23 | def solve(number): 24 | return ",".join(list(str(number))) 25 | 26 | 27 | if __name__ == "__main__": 28 | while True: 29 | try: 30 | num = int(input()) 31 | print solve(num) 32 | except EOFError: 33 | break 34 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1079.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 从键盘输入一个字符,判断它是字母、数字或其它字符。 7 | 8 | 输入 9 | 从键盘输入一个字符。注意:不用提示信息。 10 | 11 | 输出 12 | 若输入的字符是字母,输出"alphabetic character"; 13 | 14 | 若输入的字符是数字,输出"digital character"; 15 | 16 | 若输入的字符是其它字符,输出"other character"; 17 | 18 | 样例输入 19 | 6 20 | 样例输出 21 | digital character 22 | """ 23 | import string 24 | 25 | 26 | __author__ = '__L1n__w@tch' 27 | 28 | 29 | def solve(a_char): 30 | if a_char in string.ascii_letters: 31 | return "alphabetic character" 32 | elif a_char in string.digits: 33 | return "digital character" 34 | else: 35 | return "other character" 36 | 37 | if __name__ == "__main__": 38 | while True: 39 | try: 40 | char = raw_input() 41 | print solve(char) 42 | except EOFError: 43 | break 44 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1080.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 编写程序。实现根据用户输入的三角形的边长,判定是何种三角形。 7 | 8 | 输入 9 | 输入三个数(用逗号隔开),分别代表三角形的三条边。 10 | 11 | 输出 12 | /*判断三边是否构成三角形*/ 13 | { 14 |   /*如果三条边均相等,则输出为等边三角形: printf("Equilateral triangle\n"); */ 15 |   else  /*如果只有两条边相等,则输出为等腰三角形:printf("Isoceles triangle\n")*/ 16 |   else  /*如果两边的平方和等于第三边平方,则输出为直角三角形:printf("Right-angled triangle\n") */ 17 |      else /*输出为一般三角形:printf("General triangle\n");*/ 18 | } 19 | else 20 | /*输出不能构成三角形:printf("Can't make up of triangle\n"); */ 21 | 22 | 样例输入 23 | 3,4,5 24 | 样例输出 25 | Right-angled triangle 26 | """ 27 | import string 28 | 29 | __author__ = '__L1n__w@tch' 30 | 31 | 32 | def solve(question): 33 | a, b, c = question.split(",") 34 | a, b, c = int(a), int(b), int(c) 35 | if (a + b > c) and (a - b < c): 36 | if a == b == c: 37 | return "Equilateral triangle" 38 | elif (a == b and a != c) or (a == c and a != b) or (b == c and a != b): 39 | return "Isoceles triangle" 40 | elif a ** 2 + b ** 2 == c ** 2: 41 | return "Right-angled triangle" 42 | else: 43 | return "General triangle" 44 | else: 45 | return "Can't make up of triangle" 46 | 47 | 48 | if __name__ == "__main__": 49 | while True: 50 | try: 51 | problem_input = raw_input() 52 | print solve(problem_input) 53 | except EOFError: 54 | break 55 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1081.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 从键盘输入2个操作数和运算符,用switch语句实现两个数的加、减、乘、除运算。 7 | 8 | 输入 9 | 按照运算表达式的顺序输入两个操作数和运算符,如2+3或88-2或25/6或21.7*3。操作数为双精度浮点型数据,运算符为'+'或'-'或'*'或'/'。 10 | 11 | 输出 12 | 输出运算结果,结果为双精度浮点型数据。输出数据后要换行。 13 | 14 | 样例输入 15 | 21.7*7 16 | 样例输出 17 | 151.900000 18 | """ 19 | __author__ = '__L1n__w@tch' 20 | 21 | 22 | def solve(question): 23 | result = 0 24 | if "*" in question: 25 | num1, num2 = question.split("*") 26 | num1, num2 = float(num1), float(num2) 27 | result = num1 * num2 28 | elif "+" in question: 29 | num1, num2 = question.split("+") 30 | num1, num2 = float(num1), float(num2) 31 | result = num1 + num2 32 | elif "-" in question: 33 | num1, num2 = question.split("-") 34 | num1, num2 = float(num1), float(num2) 35 | result = num1 - num2 36 | elif "/" in question: 37 | num1, num2 = question.split("/") 38 | num1, num2 = float(num1), float(num2) 39 | result = num1 / num2 40 | 41 | # 保证小数点后 6 位 42 | return "{:.6f}".format(result) 43 | 44 | 45 | if __name__ == "__main__": 46 | while True: 47 | try: 48 | problem_input = raw_input() 49 | print solve(problem_input) 50 | except EOFError: 51 | break 52 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1082.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 从键盘输入一学生某科目成绩x,判断学生成绩等级。如果x<0或x>100,输出"Error";如果90<=x<=100,等级为'A';如果80<=x<90,等级为'B';如果在70<=x<80,等级为'C';如果60<=x<70,等级为'D';如果成绩小于60,等级为'E'。 7 | 8 | 输入 9 | 输入成绩x,x为单精度浮点型数据。 10 | 11 | 输出 12 | 输入数据小于0或大于100,输出字符串"Error"; 13 | 14 | 输入数据在0到100之间,输出等级,等级为一字符。或为'A';或为'B';或为'C';或为'D';或为'E'。 15 | 16 | 样例输入 17 | 99.99 18 | 样例输出 19 | A 20 | """ 21 | __author__ = '__L1n__w@tch' 22 | 23 | 24 | def solve(question): 25 | number = float(question) 26 | 27 | if 90 <= number <= 100: 28 | result = "A" 29 | elif 80 <= number < 90: 30 | result = "B" 31 | elif 70 <= number < 80: 32 | result = "C" 33 | elif 60 <= number < 70: 34 | result = "D" 35 | elif 0 <= number < 60: 36 | result = "E" 37 | else: 38 | result = "Error" 39 | 40 | return result 41 | 42 | 43 | if __name__ == "__main__": 44 | while True: 45 | try: 46 | problem_input = raw_input() 47 | print solve(problem_input) 48 | except EOFError: 49 | break 50 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1083.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 输入 6 | 输入一双精度浮点数x 7 | 8 | 输出 9 | 根据分段函数,输出x对应的y值。 10 | 11 | 样例输入 12 | 25 13 | 样例输出 14 | y=125.000000 15 | """ 16 | import math 17 | 18 | __author__ = '__L1n__w@tch' 19 | 20 | 21 | def solve(question): 22 | number = float(question) 23 | 24 | if number < 0: 25 | result = abs(number) / 2 26 | elif 0 <= number < 10: 27 | result = 3 + math.exp(number) 28 | elif 10 <= number < 20: 29 | result = math.log10(number) 30 | elif 20 <= number < 30: 31 | result = number ** 1.5 32 | elif 30 <= number < 50: 33 | result = number ** 0.5 - 1 34 | elif number >= 50: 35 | result = math.cos(number) * 3 36 | 37 | return "y={:.6f}".format(result) 38 | 39 | 40 | if __name__ == "__main__": 41 | while True: 42 | try: 43 | problem_input = raw_input() 44 | print solve(problem_input) 45 | except EOFError: 46 | break 47 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1084.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 从键盘输入一学生某科目成绩x,判断学生成绩等级。如果x<0或x>100,输出"Error";如果90<=x<=100,等级为'A';如果80<=x<90,等级为'B';如果在70<=x<80,等级为'C';如果60<=x<70,等级为'D';如果成绩小于60,等级为'E'。 7 | 8 | 输入 9 | 输入5行测试数据,每个测试数据代表一个成绩x,x为单精度浮点型数据。 10 | 11 | 输出 12 | 输入数据小于0或大于100,输出字符串"Error"; 13 | 14 | 输入数据在0到100之间,输出等级,等级为一字符。或为'A';或为'B';或为'C';或为'D';或为'E'。 15 | 16 | 根据输入的5行测试数据,对应输出5行结果,每个结果输出后要换行。 17 | 18 | 样例输入 19 | 99.99 20 | 100.7788 21 | 81 22 | 55 23 | -5.7 24 | 25 | 样例输出 26 | A 27 | Error 28 | B 29 | E 30 | Error 31 | 32 | """ 33 | 34 | __author__ = '__L1n__w@tch' 35 | 36 | 37 | def solve(question): 38 | number = float(question) 39 | 40 | if 90 <= number <= 100: 41 | result = "A" 42 | elif 80 <= number < 90: 43 | result = "B" 44 | elif 70 <= number < 80: 45 | result = "C" 46 | elif 60 <= number < 70: 47 | result = "D" 48 | elif 0 <= number < 60: 49 | result = "E" 50 | else: 51 | result = "Error" 52 | 53 | return result 54 | 55 | 56 | if __name__ == "__main__": 57 | while True: 58 | try: 59 | problem_input = raw_input() 60 | print solve(problem_input) 61 | except EOFError: 62 | break 63 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1085.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 输入 6 | 先输入一个整数n,表示后面总共要输入n组测试数据; 7 | 8 | 然后输入n组测试数据,每组测试数据是一个双精度浮点数x。 9 | 10 | 输出 11 | 根据输入的n组测试数据,对应输出n个输出结果,每个输出结果单独占一行,即每个输出结果后要加换行符。 12 | 13 | 样例输入 14 | 3 15 | 25 16 | -2 17 | 49 18 | 样例输出 19 | y=125.000000 20 | y=1.000000 21 | y=6.000000 22 | """ 23 | import math 24 | 25 | __author__ = '__L1n__w@tch' 26 | 27 | 28 | def solve(question): 29 | number = float(question) 30 | 31 | if number < 0: 32 | result = abs(number) / 2 33 | elif 0 <= number < 10: 34 | result = 3 + math.exp(number) 35 | elif 10 <= number < 20: 36 | result = math.log10(number) 37 | elif 20 <= number < 30: 38 | result = number ** 1.5 39 | elif 30 <= number < 50: 40 | result = number ** 0.5 - 1 41 | elif number >= 50: 42 | result = math.cos(number) * 3 43 | 44 | return "y={:.6f}".format(result) 45 | 46 | 47 | if __name__ == "__main__": 48 | while True: 49 | try: 50 | number_of_problems = input() 51 | for each in range(number_of_problems): 52 | problem_input = raw_input() 53 | print solve(problem_input) 54 | except EOFError: 55 | break 56 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1086.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 输入 6 | 从键盘输入一个整数n,然后按上面的公式求和。 7 | 8 | 输出 9 | 输出求和的结果s。s为双精度浮点数,精确到小数点后面8位。 10 | 11 | 样例输入 12 | 22 13 | 样例输出 14 | 0.67093591 15 | """ 16 | 17 | __author__ = '__L1n__w@tch' 18 | 19 | 20 | def solve(question): 21 | number = question 22 | result = 0 23 | 24 | for i in range(number): 25 | current_num = i + 1 26 | result += (-1) ** (current_num + 1) * (1.0 / current_num) 27 | 28 | return "{:.8f}".format(result) 29 | 30 | 31 | if __name__ == "__main__": 32 | while True: 33 | try: 34 | problem_input = input() 35 | print solve(problem_input) 36 | except EOFError: 37 | break 38 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1087.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 判断正整数x是否为素数。 7 | 8 | 质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。换句话说,只有两个正因数(1和自己)的自然数即为素数。比1大但不是素数的数称为合数。1和0既非素数也非合数。 9 | 10 | 输入 11 | 先输入一个整数n(表示后面要输入n个测试数据); 12 | 13 | 然后输入n个测试数据,每个测试数据是一个正整数x。 14 | 15 | 输出 16 | 与n个输入的正整数x相对应,输出判断结果。如果是素数,输出"Yes",不是素数,输出"No"。 17 | 18 | 样例输入 19 | 5 20 | 7 21 | 8 22 | 795 23 | 181 24 | 888 25 | 样例输出 26 | Yes 27 | No 28 | No 29 | Yes 30 | No 31 | """ 32 | # import gmpy2 33 | 34 | __author__ = '__L1n__w@tch' 35 | 36 | 37 | def is_prime_number(number): 38 | if number == 0 or number == 1: 39 | return False 40 | elif number == 2: 41 | return True 42 | for i in range(2, int(number ** 0.5 + 1)): 43 | if number % i == 0: 44 | return False 45 | 46 | return True 47 | 48 | 49 | def solve(question): 50 | number = question 51 | 52 | if is_prime_number(number): 53 | result = "Yes" 54 | else: 55 | result = "No" 56 | 57 | return result 58 | 59 | 60 | if __name__ == "__main__": 61 | while True: 62 | try: 63 | number_of_problems = input() 64 | for i in range(number_of_problems): 65 | problem_input = input() 66 | print solve(problem_input) 67 | except EOFError: 68 | break 69 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1088.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 从键盘输入一个整数n(98000<=n<=100000),统计1至n范围内,个位数是7的素数的个数。 7 | 8 | 质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。换句话说,只有两个正因数(1和自己)的自然数即为素数。比1大但不是素数的数称为合数。1和0既非素数也非合数。 9 | 10 | 输入 11 | 输入一个整数n(98000<=n<=100000) 12 | 13 | 输出 14 | 个位数为7的素数的个数 15 | 16 | 样例输入 17 | 100000 18 | 样例输出 19 | 2411 20 | """ 21 | # import gmpy2 22 | 23 | __author__ = '__L1n__w@tch' 24 | 25 | 26 | def is_prime_number(number): 27 | if number == 0 or number == 1: 28 | return False 29 | elif number == 2: 30 | return True 31 | for i in range(2, int(number ** 0.5 + 1)): 32 | if number % i == 0: 33 | return False 34 | 35 | return True 36 | 37 | 38 | def solve(question): 39 | number = question 40 | counts = 0 41 | 42 | for i in range(1, number + 1): 43 | if str(i)[-1] == "7" and is_prime_number(i): 44 | counts += 1 45 | 46 | return counts 47 | 48 | 49 | if __name__ == "__main__": 50 | while True: 51 | try: 52 | problem_input = input() 53 | print solve(problem_input) 54 | except EOFError: 55 | break 56 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1089.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 从键盘输入一个整数n(98000<=n<=100000),统计1至n范围内素数的个数。 7 | 8 | 质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。换句话说,只有两个正因数(1和自己)的自然数即为素数。比1大但不是素数的数称为合数。1和0既非素数也非合数。 9 | 10 | 输入 11 | 输入一个整数n(98000<=n<=100000) 12 | 13 | 输出 14 | 素数的个数 15 | 16 | 样例输入 17 | 100000 18 | 样例输出 19 | 9592 20 | """ 21 | # import gmpy2 22 | 23 | __author__ = '__L1n__w@tch' 24 | 25 | 26 | def is_prime_number(number): 27 | if number == 0 or number == 1: 28 | return False 29 | elif number == 2: 30 | return True 31 | for i in range(2, int(number ** 0.5 + 1)): 32 | if number % i == 0: 33 | return False 34 | 35 | return True 36 | 37 | 38 | def solve(question): 39 | number = question 40 | counts = 0 41 | 42 | for i in range(1, number + 1): 43 | if is_prime_number(i): 44 | counts += 1 45 | 46 | return counts 47 | 48 | 49 | if __name__ == "__main__": 50 | while True: 51 | try: 52 | problem_input = input() 53 | print solve(problem_input) 54 | except EOFError: 55 | break 56 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1090.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 求水仙花数。水仙花数是一个3位正整数,其值等于其各个数位的立方之和。 7 | 8 | 输入 9 | 无 10 | 11 | 输出 12 | 输出所有水仙花数,每个水仙花数单独占一行。 13 | 14 | 样例输出 15 | 153 16 | 370 17 | 371 18 | 407 19 | """ 20 | # import gmpy2 21 | 22 | __author__ = '__L1n__w@tch' 23 | 24 | 25 | def is_shuixianhua(number): 26 | raw_number = number 27 | sum_of_all = 0 28 | for each_number in str(number): 29 | sum_of_all += int(each_number) ** 3 30 | 31 | if raw_number == sum_of_all: 32 | return True 33 | else: 34 | return False 35 | 36 | 37 | def solve(): 38 | for i in range(100, 1000): 39 | if is_shuixianhua(i): 40 | print i 41 | 42 | 43 | if __name__ == "__main__": 44 | while True: 45 | try: 46 | # problem_input = input() 47 | solve() 48 | break 49 | except EOFError: 50 | break 51 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1091.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 百马百担问题。有100匹马,驮100担货,大马驮3担,中马驮2担,两匹小马1担,编程计算所有可能的驮法? 7 | 8 | 输入 9 | 无 10 | 11 | 输出 12 | 输出所有可能的驮法。 13 | 14 | 每行输出一种驮法,每种驮法依次输出: 15 | 16 | 大马数,中马数,小马数 17 | 18 | 如2,30,68 19 | 表示大马数为2,中马数为30,小马数为68 20 | 21 | 样例输出 22 | 2,30,68 23 | 5,25,70 24 | 8,20,72 25 | 11,15,74 26 | 14,10,76 27 | 17,5,78 28 | 20,0,80 29 | """ 30 | 31 | __author__ = '__L1n__w@tch' 32 | 33 | 34 | def solve(): 35 | for x in range(100 / 3): 36 | for y in range(100): 37 | z = 100 - x - y 38 | if x * 3 + y * 2 + z / 2.0 == 100: 39 | print("{},{},{}".format(x, y, z)) 40 | 41 | 42 | if __name__ == "__main__": 43 | while True: 44 | try: 45 | solve() 46 | break 47 | except EOFError: 48 | break 49 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1092.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 斐波那契数列为:0、1、1、2、3、5、8、13、21、34、55、……,根据该数列总结出的规律为: 7 | 8 | f(0)=0 9 | 10 | f(1)=1 11 | 12 | f(n)=f(n-1)+f(n-2) (当n>1时) 13 | 14 | 求斐氏数列的f(n)。 15 | 16 | 假设f(n)的值所占内存不会超过4个字节。 17 | 18 | 输入 19 | 输入包括若干行,每行输入一个正整数n,若输入-1则结束。 20 | 21 | 输出 22 | 对于每行输入的n的值,对应输出f(n),每个输出单独占一行。若输入是-1,则不输出任何结果。 23 | 24 | 样例输入 25 | 6 26 | 7 27 | 8 28 | 9 29 | -1 30 | 样例输出 31 | 8 32 | 13 33 | 21 34 | 34 35 | """ 36 | 37 | __author__ = '__L1n__w@tch' 38 | 39 | 40 | def solve(n, fib_dict): 41 | if dict(fib_dict).has_key(n): 42 | return fib_dict[n] 43 | else: 44 | max_order = len(fib_dict) - 1 45 | 46 | while max_order != n: 47 | fib_dict[max_order + 1] = fib_dict[max_order] + fib_dict[max_order - 1] 48 | max_order += 1 49 | 50 | return fib_dict[max_order] 51 | 52 | 53 | if __name__ == "__main__": 54 | fib_dict = {0: 0, 1: 1} 55 | 56 | while True: 57 | try: 58 | n = input() 59 | if n == -1: 60 | break 61 | else: 62 | print(solve(n, fib_dict)) 63 | except EOFError: 64 | break 65 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1093.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 求1-n中回文数的个数。回文数指正读和反读相同的整数,即该数和它的逆序数相等。如535,282等。 7 | 8 | 输入 9 | 输入包括多行,每行输入一个正整数n(n>=1)。若输入的正整数是0,则结束输入。 10 | 11 | 输出 12 | 与输入相对应,各行对应输出1-n中,回文数的个数。 13 | 14 | 样例输入 15 | 9 16 | 44 17 | 55 18 | 0 19 | 样例输出 20 | 9 21 | 13 22 | 14 23 | """ 24 | 25 | __author__ = '__L1n__w@tch' 26 | 27 | 28 | def is_huiwen(n): 29 | # 以下效率低一些 30 | # str_n = str(n) 31 | # return str_n == str_n[::-1] 32 | n = str(n) 33 | for i in range(len(n) / 2): 34 | if n[i] != n[len(n) - i - 1]: 35 | return False 36 | return True 37 | 38 | 39 | def solve(n): 40 | counts = 0 41 | for i in range(1, n + 1): 42 | if is_huiwen(i): 43 | counts += 1 44 | return counts 45 | 46 | 47 | if __name__ == "__main__": 48 | while True: 49 | try: 50 | n = input() 51 | if n == 0: 52 | break 53 | else: 54 | print(solve(n)) 55 | except EOFError: 56 | break 57 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/acm_1094.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | # version: Python2.X 4 | """ 5 | 题目描述 6 | 从键盘输入若干学生的成绩,输出其中的最高成绩。 7 | 8 | 输入 9 | 输入若干学生的成绩,输入负数时结束输入。 10 | 11 | 输出 12 | 输出最高成绩。 13 | 14 | 样例输入 15 | 8 16 | 34 17 | 345 18 | 353.88 19 | 23 20 | -2 21 | 样例输出 22 | 353.880000 23 | """ 24 | 25 | __author__ = '__L1n__w@tch' 26 | 27 | 28 | def solve(n): 29 | pass 30 | 31 | 32 | if __name__ == "__main__": 33 | question = list() 34 | while True: 35 | try: 36 | n = raw_input() 37 | n = float(n) 38 | if n < 0: 39 | print("{:.6f}".format(max(question))) 40 | break 41 | else: 42 | question.append(n) 43 | except EOFError: 44 | break 45 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/test_1003.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 #默认编码格式为utf-8 2 | import unittest 3 | from acm_1003 import solve 4 | 5 | 6 | class Test1003(unittest.TestCase): 7 | def test_answer(self): 8 | question = ["34", "201", "2098765413", "1717171717171717171717171717171717171717171717171718"] 9 | answer = ["1", "0", "1", "0"] 10 | my_solve = [solve(x) for x in question] 11 | self.assertTrue(all(right_answer == my_answer for right_answer, my_answer in zip(answer, my_solve))) 12 | 13 | 14 | if __name__ == "__main__": 15 | unittest.main() 16 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/test_1004.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 #默认编码格式为utf-8 2 | import unittest 3 | from acm_1004 import solve, xor 4 | 5 | 6 | class Test1003(unittest.TestCase): 7 | def test_answer(self): 8 | question = ["4", "5", "0"] 9 | answer = [["0000", "0001", "0011", "0010", "0110", "0111", "0101", "0100", "1100", "1101", "1111", "1110", 10 | "1010", "1011", "1001", "1000"], 11 | ["00000", "00001", "00011", "00010", "00110", "00111", "00101", "00100", "01100", "01101", "01111", 12 | "01110", "01010", "01011", "01001", "01000", "11000", "11001", "11011", "11010", "11110", "11111", 13 | "11101", "11100", "10100", "10101", "10111", "10110", "10010", "10011", "10001", "10000"]] 14 | for i in range(len(answer)): 15 | self.assertTrue(solve(question[i]) == answer[i]) 16 | 17 | def test_xor(self): 18 | self.assertTrue(xor("1", "1") == "0") 19 | self.assertTrue(xor("1", "0") == "1") 20 | self.assertTrue(xor("0", "1") == "1") 21 | self.assertTrue(xor("0", "0") == "0") 22 | 23 | 24 | if __name__ == "__main__": 25 | unittest.main() 26 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/before_2016_12_03/test_1005.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 #默认编码格式为utf-8 2 | import unittest 3 | from acm_1005 import solve 4 | 5 | 6 | class Test1005(unittest.TestCase): 7 | def test_answer(self): 8 | question = ["3", "The 2004, 2008 Olympic games was hold respectively in ____City and ____City.", 9 | "Athens|Beijing(Peking)", "True", 10 | "ACRush has taken part in the ICPC world finals in the year ____ and ____.", 11 | "2007|2009", "False", "Aaaa____bbbb_____.", "Ccc(cc)|Ddd(dd)", "False", "2", "Athens|Beijing", 12 | "2007|2009", "Dd|cc", "Beijing|Athens", "2009|2008", "Ddd|cc"] 13 | answer = ["5", "3"] 14 | self.assertTrue(answer == solve(question)) 15 | 16 | 17 | if __name__ == "__main__": 18 | unittest.main() 19 | -------------------------------------------------------------------------------- /深信服_sangfor_相关/sangfor_acm_oj/readme.md: -------------------------------------------------------------------------------- 1 | # 深信服 ACM 相关 2 | 3 | 深信服内部有个 ACM 平台,虽然好久没人维护了,本文件下保存的是仅有的一少部分题目和代码 -------------------------------------------------------------------------------- /深信服_sangfor_相关/智安全杯/2019复赛.md: -------------------------------------------------------------------------------- 1 | # 备注 2 | 3 | 只记录了部分题目 4 | 5 | # Q&A 6 | 7 | ```shell 8 | 1、一般情况下,用户向后台提交登录口令,后台认证成功后用户跳转到管理页面,那么当跳转发生时,数据包里面的状态码最可能是多少() 9 | A、200 10 | B、302 11 | C、100 12 | D、404 13 | 14 | 参考答案:B 15 | 301,302 都是HTTP状态的编码,都代表着某个URL发生了转移,不同之处在于: 16 | 301 redirect: 301 代表永久性转移(Permanently Moved), 17 | 302 redirect: 302 代表暂时性转移(Temporarily Moved ), 18 | 当然 Http 状态 200 标示没有任何问题发生。 19 | ``` 20 | 21 | ```shell 22 | 2、Web 应用安全的核心问题在于 23 | A、Web 服务器访问量巨大 24 | B、用户可以提交任意输入 25 | C、操作系统出现漏洞 26 | D、Web服务器存在漏洞 27 | 28 | 参考答案:B 29 | 参考:http://www.ituring.com.cn/book/tupubarticle/16851 30 | ``` 31 | 32 | ```shell 33 | 3、网络安全攻击类型多样,原理各异,其中CC攻击是当前网络中一种普遍的攻击,以下关于CC攻击说法正确的是() 34 | A、CC攻击可以直接上传webshell控制服务器 35 | B、syn flood攻击是CC攻击的一个分支 36 | C、写恶意爬虫把网站爬死的原理与CC攻击一样 37 | D、CC攻击是一种网络层的拒绝服务攻击 38 | 39 | 参考答案:C 40 | A、这是文件上传的攻击 41 | B、TCP攻击 42 | D、应该是应用层的 43 | 参考:https://my.oschina.net/xiaominmin/blog/1648784 44 | ``` 45 | 46 | ```shell 47 | 4、某站点存在 IIS6.0 解析漏洞,以下可解析的文件() 48 | A、abc.asp:xx.txt 49 | B、abc.asp.jpg 50 | C、abc.txt 51 | D、abc.asp;efg.jpg 52 | 53 | 参考答案:D 54 | https://www.secpulse.com/archives/3750.html 55 | ``` 56 | 57 | ```shell 58 | 5、关于 XSS,下列说法正确的是() 59 | A、反射型XSS漏洞可以转化成基于DOM的XSS漏洞 60 | B、XSS都是因为后端未对数据做安全检查造成的 61 | C、从Cookie中获取用户名并输出到页面的过程不会导致XSS 62 | D、CSRF是XSS的一种 63 | 64 | 参考答案:A 65 | A、这俩区别主要在于位置的不同 66 | B、也可以是浏览器前端做检查 67 | C、改COOKIE呢 68 | D、CSRF概念比较泛,比如可以系统命令执行,不依赖 XSS 69 | ``` 70 | 71 | ```shell 72 | 6、OSPF路由协议比RIP路由协议的优势表现在() 73 | A、支持协议报文验证 74 | B、路由协议使用组播技术 75 | C、没有环路 76 | D、支持可变长子网掩码 77 | 78 | 参考答案:D 79 | RIPv2才开始支持可变长子网掩码 80 | https://www.cnblogs.com/rusty/archive/2011/03/18/1987782.html 81 | ``` 82 | 83 | ```shell 84 | 7、网关冗余的主流解决方案不包括哪些?() 85 | A、VRRP 86 | B、HRSP 87 | C、GLBP 88 | D、代理ARP 89 | 90 | 参考答案:B或D 91 | B、书写拼错了,HSRP 92 | D、代理ARP不主流,比较早期了 93 | https://jingyan.baidu.com/article/414eccf64e96bd6b421f0a63.html 94 | ``` 95 | 96 | ```shell 97 | 8、如果企业内部需要连接入Internet的用户一共有 400 个,但该企业只申请到一个 C 类的合法 IP 地址,则应该使用哪种 NAT 方式实现() 98 | A、NAPT 99 | B、动态NAT 100 | C、TCP负载均衡 101 | D、静态NAT 102 | 103 | 参考答案:B 104 | D、静态NAT是一对一转换 105 | ``` 106 | 107 | ```shell 108 | 9、为了将几个已经分片的数据按照顺序重新组装,目的主机需要使用 IP 数据报头中的哪个字段()? 109 | A、偏移字段 110 | B、服务类型ToS字段 111 | C、TTL字段 112 | D、首部长度字段 113 | 114 | 参考答案:A 115 | ``` 116 | 117 | ```shell 118 | 10、某个网站,不需要知道密码就可以直接登录任意用户账号,这个网站最可能存在什么漏洞() 119 | A、越权 120 | B、XSS 121 | C、CSRF 122 | D、SQL注入 123 | 124 | 参考答案:D 125 | ``` 126 | 127 | ```shell 128 | 11、在 NAT 环境下通过什么技术可以解决多 VPN 连接的问题?() 129 | A、GRE 130 | B、NAT-T 131 | C、TRUNK 132 | D、NAPT 133 | 134 | 参考答案:B 135 | https://zh.wikipedia.org/zh-hans/NAT%E7%A9%BF%E9%80%8F 136 | IPsec VPN客户普遍使用NAT-T来达到使ESP包通过NAT的目的。 137 | ``` 138 | 139 | ```shell 140 | 12、关于CSRF,下列说法错误的是() 141 | A、CSRF本质是盗用受害者身份,以受害者名义发送恶意请求 142 | B、CSRF能够获取受害者的 Cookie 信息 143 | C、验证 HTTP 头的 Refer 是防御 CSRF 的方法之一 144 | D、CSRF 的全称是 Cross Site Request Foregery 145 | 146 | 参考答案:B 147 | ``` 148 | 149 | ```shell 150 | 13、在实际应用中,我们有时候会将大的数据进行分片,分成多个小的数据进行传输,请问以上分片(分段)归属于OSI哪个层级负责?() 151 | A、数据链路层 152 | B、网络层 153 | C、物理层 154 | D、传输层 155 | 156 | 参考答案:D 157 | https://www.nowcoder.com/questionTerminal/23e28e5041664bcaabffdaf80d334849 158 | ``` 159 | 160 | ```shell 161 | 14、请简述SQL漏洞产生的原因? 162 | 163 | 参考答案: 164 | 其成因可以归结为以下两点原因叠加造成的: 165 | 1.程序编写者再处理程序和数据库交互的时候,使用字符拼接的方法构造SQL语句 166 | 2.未对用户可控参数进行足够的过滤便将参数内容拼接进入到SQL语句中 167 | 168 | 参考:https://blog.csdn.net/qq_29920751/article/details/51661257 169 | 参考2:https://www.jianshu.com/p/282a0d3b2afe 170 | ``` 171 | 172 | ```shell 173 | 15、请简述利用 SQL 漏洞进行脱库的全过程? 174 | 175 | 参考答案: 176 | 1、手动找出注入点 177 | 2、sqlmap -u http://www.******.com/subcat.php?id=2 --dump-all 178 | 179 | 参考:http://www.voidcn.com/article/p-uivrlyls-xe.html 180 | ``` 181 | 182 | ```shell 183 | 16、请简述 SQL 的防御办法? 184 | 185 | 参考答案: 186 | 采用sql语句预编译和绑定变量,是防御sql注入的最佳方法 187 | 但是不是所有场景都能够采用 sql语句预编译,有一些场景必须的采用 字符串拼接的方式,此时,我们严格检查参数的数据类型,还有可以使用一些安全函数,来防止sql注入。 188 | 189 | 参考:https://www.cnblogs.com/digdeep/p/4715245.html 190 | ``` 191 | 192 | ```shell 193 | 17、在 NAT 环境下应该使用哪种 VPN 封装格式和传输模式? 194 | 18、在 NAT 环境多条 VPN 连接的场景下,标准 IPSEC VPN 存在什么问题? 195 | 19、如何解决此问题,请详细说明实现原理? 196 | ``` -------------------------------------------------------------------------------- /深信服_sangfor_相关/智安全杯/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 智安全杯,参考:https://mp.weixin.qq.com/s?__biz=MjM5MzQzNTc1MA==&mid=2650828754&idx=1&sn=30605164b52f6df2b7a428bb4a4a21b1&key=41cacdd5e50db66b37eac97ce463d7582d82b656a0a654d862240049db0ad878e05e98d93f181fc00893df3033f06938ec976743fe8f0ec342218426d4eed1a62f0f557615c279fc0e57bdd981d7b3c0&ascene=1&uin=MTIyMDgxMzYw&devicetype=Windows+10&version=62060833&lang=zh_CN&pass_ticket=OGOgAtfttdnMn3SmiD4s%2F5tOyqxx2dPm9bM4KCgn1Xs%3D -------------------------------------------------------------------------------- /编程题汇总.md: -------------------------------------------------------------------------------- 1 | ## 已整理清单 2 | 3 | * 腾讯 2017 暑期实习生编程题 4 | * 构造回文 5 | * 算法基础-字符移位 6 | * 有趣的数字 7 | * 剑指 Offer 编程题练习 8 | * 二维数组中的查找 9 | * 从尾到头打印链表 10 | * 旋转数组的最小数字 11 | * 替换空格 12 | * 用两个栈实现队列 13 | * 重建二叉树 14 | * 网易 2017 校招笔试编程题 15 | * 二进制权重 16 | * 平方串 17 | * 数位和 -------------------------------------------------------------------------------- /网易 2017 校招笔试编程题/binary_weight.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 20160924 发现原来只是 index == len(reverse_temp) - 1: 那里写错了, 改过来之后能够通过测试了 6 | 20160924 这是之前只能通过 50% 例子的版本, 现在利用测试找出算法缺陷 7 | """ 8 | 9 | __author__ = '__L1n__w@tch' 10 | 11 | 12 | def get_weight(number): 13 | return bin(number).count("1") 14 | 15 | 16 | def get_start_number(number): 17 | temp = bin(number)[2:] 18 | reverse_temp = temp[::-1] 19 | flag = False 20 | for index in range(len(reverse_temp)): 21 | # 查找到 0 22 | if reverse_temp[index] == "0" and flag == False: 23 | continue 24 | # 找到所要找的数字了 25 | if reverse_temp[index] == "1": 26 | flag = True 27 | # 找到最后一个数字了 28 | if index == len(reverse_temp) - 1: 29 | result = "1" + "0" * (index + 1) 30 | return int(result, 2) 31 | if reverse_temp[index] == "0" and flag == True: 32 | result = "0" * index + "1" + reverse_temp[index + 1:] 33 | result = result[::-1] 34 | return int(result, 2) 35 | 36 | 37 | def solve(number): 38 | start_number = get_start_number(number) 39 | weight_n = get_weight(number) 40 | for i in range(start_number, 1000000000): 41 | if get_weight(i) == weight_n: 42 | return i 43 | 44 | 45 | if __name__ == "__main__": 46 | solve(1) 47 | -------------------------------------------------------------------------------- /网易 2017 校招笔试编程题/readme.md: -------------------------------------------------------------------------------- 1 | ## 网易 2017 校招笔试编程题 2 | 3 | 总共记录三道题: 4 | 5 | * 二进制权重 6 | * 平方串 7 | * 数位和 -------------------------------------------------------------------------------- /网易 2017 校招笔试编程题/test_binary_weight.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 这里的版本是一个超时但是正确的版本, 用这个版本来进行测试 6 | """ 7 | import unittest 8 | from binary_weight import solve 9 | 10 | __author__ = '__L1n__w@tch' 11 | 12 | 13 | class TestBinaryWeightSolve(unittest.TestCase): 14 | def test_solve(self): 15 | for i in range(1, 1000000000): 16 | test_answer = solve(i) 17 | right_answer = TestBinaryWeightSolve.__right_answer(i) 18 | log_message = "i = {}, right: {}, my_answer: {}".format(i, right_answer, test_answer) 19 | self.assertEqual(right_answer, test_answer, log_message) 20 | 21 | @staticmethod 22 | def __right_answer(n): 23 | weight_n = TestBinaryWeightSolve.__get_weight(n) 24 | for i in range(n + 1, 1000000000): 25 | if TestBinaryWeightSolve.__get_weight(i) == weight_n: 26 | return i 27 | raise RuntimeError("[*] 自己的算法有问题了") 28 | 29 | @staticmethod 30 | def __get_weight(number): 31 | return bin(number).count("1") 32 | 33 | 34 | if __name__ == "__main__": 35 | pass 36 | -------------------------------------------------------------------------------- /网易 2017 校招笔试编程题/二进制权重.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 3 | 一个数的二进制权重被定义为一个十进制数表示为二进制数中 '1' 的个数。例如: 4 | 5 | 1 的二进制权重就是 1 6 | 7 | 1717 表示为二进制数为 11010110101,所以二进制权重为 7 8 | 9 | 现在给出一个正整数 N,返回最小的一个大于 N 并且二进制权重跟 N 相同的数。 10 | 11 | 输入描述: 12 | 13 | > 输入一个数 N(1 <= N <= 1,000,000,000) 14 | 15 | 输出描述: 16 | 17 | > 输出一个数,即为最小的一个大于 N 并且二进制权重跟 N 相同的数 18 | 19 | 输入例子: 20 | 21 | > 1717 22 | 23 | 输出例子: 24 | 25 | > 1718 26 | 27 | # 自己的解答 28 | 29 | ## 正确但是超时的解答 30 | 31 | ```python 32 | def get_weight(number): 33 | return bin(number).count("1") 34 | 35 | n = int(sys.stdin.readline().strip()) 36 | weight_n = get_weight(n) 37 | for i in range(n + 1, 1000000000): 38 | if get_weight(i) == weight_n: 39 | print(i) 40 | ``` 41 | 42 | ## 尝试优化的代码 43 | 44 | 由于自己当时笔试的时候写出来的版本只能通过 50% 的例子,所以下面先写个测试代码,再来改进自己的优化算法: 45 | 46 | ```python 47 | # 测试代码 48 | #!/bin/env python3 49 | # -*- coding: utf-8 -*- 50 | # version: Python3.X 51 | """ 52 | 这里的版本是一个超时但是正确的版本, 用这个版本来进行测试 53 | """ 54 | import unittest 55 | from binary_weight import solve 56 | 57 | __author__ = '__L1n__w@tch' 58 | 59 | 60 | class TestBinaryWeightSolve(unittest.TestCase): 61 | def test_solve(self): 62 | for i in range(1, 1000000000): 63 | test_answer = solve(i) 64 | right_answer = TestBinaryWeightSolve.__right_answer(i) 65 | log_message = "i = {}, right: {}, my_answer: {}".format(i, right_answer, test_answer) 66 | self.assertEqual(right_answer, test_answer, log_message) 67 | 68 | @staticmethod 69 | def __right_answer(n): 70 | weight_n = TestBinaryWeightSolve.__get_weight(n) 71 | for i in range(n + 1, 1000000000): 72 | if TestBinaryWeightSolve.__get_weight(i) == weight_n: 73 | return i 74 | raise RuntimeError("[*] 自己的算法有问题了") 75 | 76 | @staticmethod 77 | def __get_weight(number): 78 | return bin(number).count("1") 79 | 80 | 81 | if __name__ == "__main__": 82 | pass 83 | ``` 84 | 85 | ## 通过测试的代码,不知道效率如何 86 | 87 | ```python 88 | #!/bin/env python3 89 | # -*- coding: utf-8 -*- 90 | # version: Python3.X 91 | """ 92 | 20160924 发现原来只是 index == len(reverse_temp) - 1: 那里写错了, 改过来之后能够通过测试了 93 | 20160924 这是之前只能通过 50% 例子的版本, 现在利用测试找出算法缺陷 94 | """ 95 | 96 | __author__ = '__L1n__w@tch' 97 | 98 | 99 | def get_weight(number): 100 | return bin(number).count("1") 101 | 102 | 103 | def get_start_number(number): 104 | temp = bin(number)[2:] 105 | reverse_temp = temp[::-1] 106 | flag = False 107 | for index in range(len(reverse_temp)): 108 | # 查找到 0 109 | if reverse_temp[index] == "0" and flag == False: 110 | continue 111 | # 找到所要找的数字了 112 | if reverse_temp[index] == "1": 113 | flag = True 114 | # 找到最后一个数字了 115 | if index == len(reverse_temp) - 1: 116 | result = "1" + "0" * (index + 1) 117 | return int(result, 2) 118 | if reverse_temp[index] == "0" and flag == True: 119 | result = "0" * index + "1" + reverse_temp[index + 1:] 120 | result = result[::-1] 121 | return int(result, 2) 122 | 123 | 124 | def solve(number): 125 | start_number = get_start_number(number) 126 | weight_n = get_weight(number) 127 | for i in range(start_number, 1000000000): 128 | if get_weight(i) == weight_n: 129 | return i 130 | 131 | 132 | if __name__ == "__main__": 133 | solve(1) 134 | ``` 135 | 136 | -------------------------------------------------------------------------------- /网易 2017 校招笔试编程题/平方串.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 3 | 如果一个字符串由完全相同的两段字符组成,我们称其为平方串。例如: 4 | 5 | 'aa','ABAB','abcabc' 是平方串。 6 | 7 | 'aaa','ABCabc','abcab' 不是平方串。 8 | 9 | 现在给出一个字符串求它所有的连续子串中有多少种平方串。 10 | 11 | 例如: 12 | 13 | 'aaabccabccCC',我们会发现 'aa','abccabcc','cc',and 'CC' 这四种平方串。其中 'aa', 'cc' 都出现了 2 次,但是我们只统计一次种树。 14 | 15 | 输入描述: 16 | 17 | > 输入为一个字符串,长度 length(0 <= length <= 50)。只包含大小写字母。 18 | 19 | 输出描述: 20 | 21 | > 输出一个整数,即为所求的种数 22 | 23 | 输入例子: 24 | 25 | > aaabccabccCC 26 | 27 | 输出例子: 28 | 29 | > 4 30 | 31 | # 自己的解答 32 | 33 | 以下这个解答只能通过示例,其他例子还没试,当时还没来得及提交就结束考试了。 34 | 35 | ```python 36 | def is_pingfang(text): 37 | if len(text) == 1: 38 | return False 39 | elif len(text) % 2 != 0: 40 | return False 41 | else: 42 | return text[len(text) // 2:] == text[:len(text) // 2] 43 | 44 | 45 | text = "aaabccabccCC" 46 | result_set = list() 47 | 48 | for i in range(len(text)): 49 | for j in range(1, len(text) - i + 1): 50 | test = text[i:i + j] 51 | if is_pingfang(test): 52 | result_set.append(test) 53 | 54 | # print(result_set) 55 | print(len(set(result_set))) 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /网易 2017 校招笔试编程题/数位和.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 一个数字的数位和定义为这个数字所有位置的数值的总和.例如: 3 | 1234 的数位和为: `1 + 2 + 3 + 4 = 10` 4 | 5463 的数位和为: `5 + 4 + 6 + 3 = 18` 5 | 现在有 3 个数 A、B、C, 需要你求出在在 A、B 范围内(包括 A、B)的一个数 X,让 X 的数位和与 C 的数位和差值的绝对值最小。 6 | 7 | 输入描述: 8 | 9 | > 输入为一行,一行有 3 个数 A、B、C,使用空格隔开。 10 | > 11 | > (`1 <= A, B, C <= 1,000,000,000`) 12 | > 13 | > (`0 <= B - A <= 100,000`) 14 | 15 | 输出描述: 16 | 17 | > 输出一个数,即为所求得 X,如果有多解输出最小的那个解。 18 | 19 | 输入例子: 20 | 21 | > 1 9 10 22 | 23 | 输出例子: 24 | 25 | > 1 26 | 27 | # 自己的解答 28 | 29 | ```python 30 | import sys 31 | 32 | def get_sum(number): 33 | number = str(number) 34 | result = 0 35 | for each_num in number: 36 | result += int(each_num) 37 | return result 38 | 39 | 40 | def solve(A, B, C_sum): 41 | min_result = 100000 42 | min_x = B + 1 43 | for x in range(A, B + 1): 44 | temp = abs(get_sum(x) - C_sum) 45 | if temp < min_result: 46 | min_result = temp 47 | min_x = x 48 | return min_x 49 | 50 | 51 | line = sys.stdin.readline().strip() 52 | values = map(int, line.split()) 53 | A, B, C = values[0], values[1], values[2] 54 | c_value = get_sum(C) 55 | print(solve(A, B, c_value)) 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/README.md: -------------------------------------------------------------------------------- 1 | # 清单 2 | * 求取最长回文子串 3 | * 构造回文 4 | * 算法基础-字符移位 -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/get_longest_palindromic_substring.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 参考资料: 6 | http://www.cnblogs.com/TenosDoIt/p/3675788.html 7 | 8 | 里面提到了 4 个算法: 9 | 1. 暴力解法,枚举所有子串,对每个子串判断是否为回文,复杂度为O(n^3) 10 | 2. 删除暴力解法中有很多重复的判断。很容易想到动态规划,时间复杂度O(n^2),空间O(n^2),动态规划方程如下: 11 | dp[i][j] 表示子串s[i…j]是否是回文 12 | 初始化:dp[i][i] = true (0 <= i <= n-1); dp[i][i-1] = true (1 <= i <= n-1); 其余的初始化为false 13 | dp[i][j] = (s[i] == s[j] && dp[i+1][j-1] == true) 14 | 在动态规划中保存最长回文的长度及起点即可 15 | 3. 以某个元素为中心,分别计算偶数长度的回文最大长度和奇数长度的回文最大长度。时间复杂度O(n^2),空间O(1) 16 | 4. Manacher算法,时间复杂度O(n), 空间复杂度O(n) 17 | 查看原文链接 18 | """ 19 | 20 | __author__ = '__L1n__w@tch' 21 | 22 | 23 | # 动态规划解决 24 | def dynamic_solve(s): 25 | """ 26 | 动态规划解决, 方程为: 27 | dp[i][j] 表示子串 s[i...j] 是否是回文 28 | 初始化: 29 | dp[i][i] = true (0 <= i <= n - 1) ; dp[i][i - 1] = true (1 <= i <= n - 1); 其余的初始化为 false 30 | 方程: 31 | dp[i][j] = (s[i] == s[j] && dp[i+1][j-1] == true) 32 | 33 | :param s: 34 | :return: 35 | """ 36 | pass 37 | 38 | 39 | # 枚举中心法 40 | def center_enumerate(s): 41 | """ 42 | 以某个元素为中心,分别计算偶数长度的回文最大长度和奇数长度的回文最大长度。时间复杂度O(n^2),空间O(1) 43 | :param s: 待求的字符串 44 | :return: 最大长度 45 | """ 46 | length = len(s) 47 | if length <= 1: 48 | return s 49 | 50 | start, max_length = 0, 0 51 | for i in range(1, length): 52 | # 寻找以 i-1, i 为中点偶数长度的回文 53 | low, high = i - 1, i 54 | while low >= 0 and high < length and s[low] == s[high]: 55 | low -= 1 56 | high += 1 57 | if high - low - 1 > max_length: 58 | max_length = high - low - 1 59 | start = low + 1 60 | 61 | # 寻找以 i 为中心的奇数长度的回文 62 | low, high = i - 1, i + 1 63 | while low >= 0 and high < length and s[low] == s[high]: 64 | low -= 1 65 | high += 1 66 | if high - low - 1 > max_length: 67 | max_length = high - low - 1 68 | start = low + 1 69 | 70 | return s[start:max_length] 71 | 72 | 73 | if __name__ == "__main__": 74 | tests = ["abcda", "google"] 75 | for each_test in tests: 76 | print(center_enumerate(each_test)) 77 | -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/字符移位/readme.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。 3 | 4 | 你能帮帮小Q吗? 5 | 6 | 输入描述: 7 | 8 | 输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000. 9 | 10 | 11 | 12 | 输出描述: 13 | 14 | 对于每组数据,输出移位后的字符串。 15 | 16 | 输入例子: 17 | 18 | AkleBiCeilD 19 | 20 | 输出例子: 21 | 22 | kleieilABCD -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/字符移位/solve.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | # 参考资料 6 | http://www.cnblogs.com/duanguyuan/p/5675179.html 7 | # 思路 8 | 遍历 + 移动 9 | """ 10 | __author__ = '__L1n__w@tch' 11 | 12 | 13 | def no_extra_space_swap(a, b): 14 | """ 15 | 不能构建额外空间, 那么交换移动元素使用位操作的那个版本 swap() 16 | 原理是异或了 2 次相当于没有异或 17 | :param a: 'a' 18 | :param b: 'b' 19 | :return: 'b', 'a' 20 | """ 21 | a, b = ord(a), ord(b) 22 | a ^= b 23 | b ^= a 24 | a ^= b 25 | return chr(a), chr(b) 26 | 27 | 28 | def post_order_move(s): 29 | """ 30 | 把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。 31 | :param s: "AkleBiCeilD" 32 | :return: "kleieilABCD" 33 | """ 34 | s = list(s) 35 | last = len(s) - 1 36 | for i in range(last, -1, -1): 37 | if s[i].islower(): 38 | continue 39 | else: 40 | s[i], s[last] = no_extra_space_swap(s[i], s[last]) 41 | for j in range(i, last - 1): 42 | s[j], s[j + 1] = no_extra_space_swap(s[j], s[j + 1]) 43 | last -= 1 44 | 45 | return "".join(s) 46 | 47 | 48 | if __name__ == "__main__": 49 | tests = ["AkleBiCeilD"] 50 | for each_test in tests: 51 | assert post_order_move(each_test) == "kleieilABCD" 52 | -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/有趣的数字.md: -------------------------------------------------------------------------------- 1 | ## 有趣的数字 2 | 3 | ### 题目描述 4 | 小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,差的绝对值最小的有多少对呢?差的绝对值最大的呢? 5 | 6 | 输入描述: 7 | 8 | 输入包含多组测试数据。 9 | 10 | 对于每组测试数据: 11 | 12 | N - 本组测试数据有n个数 13 | 14 | a1,a2...an - 需要计算的数据 15 | 16 | 保证: 17 | 18 | 1<=N<=100000,0<=ai<=INT_MAX. 19 | 20 | 输出描述: 21 | 22 | 对于每组数据,输出两个数,第一个数表示差的绝对值最小的对数,第二个数表示差的绝对值最大的对数。 23 | 24 | 输入例子: 25 | 26 | 6 27 | 28 | 45 12 45 32 5 6 29 | 30 | 输出例子: 31 | 32 | 1 2 33 | 34 | ### 说明 35 | 自己在网上找了 Python 的正确答案, 然后写单元测试不断测试自己的答案, 详见对应文件夹下的 unittest_solve 36 | 37 | 38 | ### 最终提交 39 | 虽然写得很丑...漂亮版本的参考单元测试里面的 `right_answer` 吧 40 | 41 | ```python 42 | from collections import OrderedDict 43 | 44 | __author__ = '__L1n__w@tch' 45 | 46 | 47 | def solve(n, data): 48 | """ 49 | 求解出差的绝对值最小的对数以及差的绝对值最大的对数 50 | :param n: 待输入数据的个数, such as 6 51 | :param data: 待输入的数据, such as [45, 12, 45, 32, 5, 6] 52 | :return: 差的绝对值最小的对数, 差的绝对值最大的对数, 比如 (1, 2) 53 | """ 54 | data = sorted(list(map(int, data.split()))) 55 | 56 | # 读取时创建字典, 判断是否有重复数字 57 | od = OrderedDict() 58 | has_same_number = False 59 | min_abs_sub_pairs, max_abs_sub_pairs = 0, 0 60 | 61 | if n == 1: 62 | return "{} {}".format(0, 0) 63 | 64 | for each_number in data: 65 | value = od.get(each_number, 0) 66 | if value > 0: 67 | has_same_number = True 68 | od[each_number] = value + 1 69 | 70 | # if 分支, 有重复数字则遍历求取, 每个有重复数字能提供 n * (n - 1) / 2 对 71 | if has_same_number: 72 | for each_number in od: 73 | min_abs_sub_pairs += od[each_number] * (od[each_number] - 1) // 2 74 | else: # 无重复数字则依次遍历求取 75 | temp_od = od.copy() # 拷贝一份以便后面处理 76 | pre_items = temp_od.popitem(last=False) # 获取最小项 77 | min_abs_sub = -1 # 初始化 78 | 79 | # 遍历每一项 80 | for next_items in temp_od.items(): 81 | if min_abs_sub == -1 or abs(pre_items[0] - next_items[0]) < min_abs_sub: 82 | min_abs_sub = abs(pre_items[0] - next_items[0]) 83 | min_abs_sub_pairs = pre_items[1] * next_items[1] 84 | elif min_abs_sub == abs(pre_items[0] - next_items[0]): 85 | min_abs_sub_pairs += pre_items[1] * next_items[1] 86 | pre_items = next_items 87 | 88 | # 计算绝对值最大的对数, 最高和最低个数乘积即可 89 | max_abs_sub_pairs = od.popitem(last=True)[1] * od.popitem(last=False)[1] 90 | 91 | return "{} {}".format(min_abs_sub_pairs, max_abs_sub_pairs) 92 | 93 | if __name__ == "__main__": 94 | while True: 95 | try: 96 | length = int(input()) 97 | data = raw_input() 98 | print solve(length, data) 99 | except EOFError: 100 | break 101 | ``` -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/有趣的数字/readme.md: -------------------------------------------------------------------------------- 1 | # 题目描述 2 | 小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,差的绝对值最小的有多少对呢?差的绝对值最大的呢? 3 | 4 | 输入描述: 5 | 6 | 输入包含多组测试数据。 7 | 8 | 对于每组测试数据: 9 | 10 | N - 本组测试数据有n个数 11 | 12 | a1,a2...an - 需要计算的数据 13 | 14 | 保证: 15 | 16 | 1<=N<=100000,0<=ai<=INT_MAX. 17 | 18 | 19 | 20 | 输出描述: 21 | 22 | 对于每组数据,输出两个数,第一个数表示差的绝对值最小的对数,第二个数表示差的绝对值最大的对数。 23 | 24 | 输入例子: 25 | 26 | 6 27 | 28 | 45 12 45 32 5 6 29 | 30 | 输出例子: 31 | 32 | 1 2 -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/有趣的数字/solve.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 有n个数,两两组成二元组,差的绝对值最小的有多少对呢?差的绝对值最大的呢? 6 | 保证: 7 | 1<=N<=100000,0<=ai<=INT_MAX. 8 | 9 | 输出描述: 10 | 对于每组数据,输出两个数,第一个数表示差的绝对值最小的对数,第二个数表示差的绝对值最大的对数。 11 | 输入例子: 12 | 6 13 | 45 12 45 32 5 6 14 | 输出例子: 15 | 1 2 16 | 17 | 以下参考网上的思路编写的 18 | """ 19 | from collections import OrderedDict 20 | 21 | __author__ = '__L1n__w@tch' 22 | 23 | 24 | def solve(n, data): 25 | """ 26 | 求解出差的绝对值最小的对数以及差的绝对值最大的对数 27 | :param n: 待输入数据的个数, such as 6 28 | :param data: 待输入的数据, such as [45, 12, 45, 32, 5, 6] 29 | :return: 差的绝对值最小的对数, 差的绝对值最大的对数, 比如 (1, 2) 30 | """ 31 | data = sorted(list(map(int, data.split()))) 32 | 33 | # 读取时创建字典, 判断是否有重复数字 34 | od = OrderedDict() 35 | has_same_number = False 36 | min_abs_sub_pairs, max_abs_sub_pairs = 0, 0 37 | 38 | if n == 1: 39 | return "{} {}".format(0, 0) 40 | 41 | for each_number in data: 42 | value = od.get(each_number, 0) 43 | if value > 0: 44 | has_same_number = True 45 | od[each_number] = value + 1 46 | 47 | # if 分支, 有重复数字则遍历求取, 每个有重复数字能提供 n * (n - 1) / 2 对 48 | if has_same_number: 49 | for each_number in od: 50 | min_abs_sub_pairs += od[each_number] * (od[each_number] - 1) // 2 51 | else: # 无重复数字则依次遍历求取 52 | temp_od = od.copy() # 拷贝一份以便后面处理 53 | pre_items = temp_od.popitem(last=False) # 获取最小项 54 | min_abs_sub = -1 # 初始化 55 | 56 | # 遍历每一项 57 | for next_items in temp_od.items(): 58 | if min_abs_sub == -1 or abs(pre_items[0] - next_items[0]) < min_abs_sub: 59 | min_abs_sub = abs(pre_items[0] - next_items[0]) 60 | min_abs_sub_pairs = pre_items[1] * next_items[1] 61 | elif min_abs_sub == abs(pre_items[0] - next_items[0]): 62 | min_abs_sub_pairs += pre_items[1] * next_items[1] 63 | pre_items = next_items 64 | 65 | # 计算绝对值最大的对数, 最高和最低个数乘积即可 66 | max_abs_sub_pairs = od.popitem(last=True)[1] * od.popitem(last=False)[1] 67 | 68 | return "{} {}".format(min_abs_sub_pairs, max_abs_sub_pairs) 69 | 70 | 71 | def right(n, a): 72 | try: 73 | n = n 74 | a = list(map(int, a.split())) 75 | # n = input() 76 | # a = map(int, input().split()) 77 | except: 78 | exit() 79 | if n == 1: 80 | return 0, 0 81 | else: 82 | a = sorted(a) 83 | m = a[1] - a[0] 84 | for i in range(2, n): 85 | m = min(m, a[i] - a[i - 1]) 86 | if m == 0: 87 | break 88 | cnt = 0 89 | if m == 0: 90 | from itertools import groupby 91 | for k, v in groupby(a): 92 | l = len(list(v)) 93 | cnt += (l - 1) * l // 2 94 | else: 95 | for i in range(1, n): 96 | if a[i] - a[i - 1] == m: 97 | cnt += 1 98 | return cnt, n * (n - 1) // 2 if a[0] == a[-1] else a.count(a[0]) * a.count(a[-1]) 99 | 100 | 101 | if __name__ == "__main__": 102 | length = 6 103 | a_list = "6173 1649 3865 7865 4549 8549" 104 | print(solve(length, a_list)) 105 | print(right(length, a_list)) 106 | -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/有趣的数字/unittest_solve.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 自己写的只能通过 10%, 只好写个单元测试来测试自己哪里错了 6 | """ 7 | import unittest 8 | import random 9 | from solve import solve 10 | 11 | __author__ = '__L1n__w@tch' 12 | 13 | 14 | class TestMine(unittest.TestCase): 15 | def test_my_answer(self): 16 | for i in range(233): 17 | length = random.randint(1, 10 ** 3) 18 | a_list = str() 19 | for j in range(length): 20 | a_list += "{} ".format(random.randint(0, 10 ** 4)) 21 | 22 | right_answer = "{} {}".format(*right(length, a_list)) 23 | my_answer = solve(length, a_list) 24 | self.assertEqual(right_answer, my_answer) 25 | 26 | 27 | def right(n, a): 28 | try: 29 | n = n 30 | a = list(map(int, a.split())) 31 | # n = input() 32 | # a = map(int, input().split()) 33 | except: 34 | exit() 35 | if n == 1: 36 | return 0, 0 37 | else: 38 | a = sorted(a) 39 | m = a[1] - a[0] 40 | for i in range(2, n): 41 | m = min(m, a[i] - a[i - 1]) 42 | if m == 0: 43 | break 44 | cnt = 0 45 | if m == 0: 46 | from itertools import groupby 47 | for k, v in groupby(a): 48 | l = len(list(v)) 49 | cnt += (l - 1) * l // 2 50 | else: 51 | for i in range(1, n): 52 | if a[i] - a[i - 1] == m: 53 | cnt += 1 54 | return cnt, n * (n - 1) // 2 if a[0] == a[-1] else a.count(a[0]) * a.count(a[-1]) 55 | 56 | 57 | if __name__ == "__main__": 58 | unittest.main() 59 | -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/构造回文.md: -------------------------------------------------------------------------------- 1 | ## 构造回文 2 | 3 | ### 题目描述 4 | 5 | 给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?输出需要删除的字符个数。 6 | 7 | 输入描述:输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000. 8 | 9 | 输出描述:对于每组数据,输出一个整数,代表最少需要删除的字符个数。 10 | 11 | 输入例子: 12 | 13 | abcdagoogle 14 | 15 | 输出例子: 16 | 17 | 22 18 | 19 | ### 参考资料 20 | 21 | [删除最少字符使字符串成为回文串](http://www.voidcn.com/blog/Do_Know/article/p-5978576.html) 22 | 23 | ### 分析 24 | 25 | 对于这题来说,插入字符和删除字符使其成为回文串,答案是一样的.首先求s的反串rs,然后对s和rs求最长公共子序列,要删除的字符个数就是 LCS. 26 | 27 | ### Python 解答 28 | 自己用 Python 写了, 虽然结果正确, 但是超时了。思路是用动态规划。 29 | ```python 30 | #!/bin/env python3 31 | # -*- coding: utf-8 -*- 32 | # version: Python3.X 33 | """ 34 | # 题目描述 35 | 给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?输出需要删除的字符个数。 36 | 37 | # 参考资料 38 | http://www.voidcn.com/blog/Do_Know/article/p-5978576.html 39 | 40 | # 分析 41 | 对于这题来说,插入字符和删除字符使其成为回文串,答案是一样的. 42 | 43 | 首先求s的反串rs,然后对s和rs求最长公共子序列,要删除的字符个数就是 LCS. 44 | """ 45 | 46 | __author__ = '__L1n__w@tch' 47 | 48 | MAX_LENGTH = 1010 # 1 <= s <= 1000 49 | 50 | 51 | # 答案用动态规划解决的 52 | def dynamic_solve(s): 53 | """ 54 | 动态规划求取构造回文要删除的字符个数 55 | dp[i][j] 表示 s1 的前 i 个字符串, s2 的后 j 个字符串中的最大公共字串 56 | 57 | 动态方程: 58 | dp[i + 1][j + 1] = dp[i][j] + 1 if s1[i] == s2[j] else max(dp[i][j + 1], dp[i + 1][j]) 59 | :param s: 原始字符串 60 | :return: 需要删除的字符个数 61 | """ 62 | # 先求反串 63 | length = len(s) 64 | reversed_s = s[::-1] 65 | 66 | # 求最长公共子序列 67 | dp = [[0 for i in range(MAX_LENGTH)] for i in range(MAX_LENGTH)] # 初始化 68 | 69 | for i in range(length): 70 | for j in range(length): 71 | if s[i] == reversed_s[j]: 72 | dp[i + 1][j + 1] = dp[i][j] + 1 73 | else: 74 | dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]) 75 | 76 | return length - dp[length][length] # 长度减去最长公共子序列即为所求 77 | 78 | 79 | if __name__ == "__main__": 80 | tests = ["", "a", "ab", "abcda", "google", 81 | "zgtklhfzomzjckwmluvivvcmhjrwkuvcjrxojobpdedpamdshcwwsetfbacvonecrdvugeibglvhxuymjvoryqjwullvzglqazxrdmczyvbgakjagttrezmvrlptiwoqkrtxuroeqmryzsgokopxxdpbejmtwvpnaqrgqladdszhdwxfckmewhdvihgvacueqhvwvjxoitlpfrckxkuksaqzjpwgoldyhugsacflcdqhifldoaphgdbhaciixouavqxwlghadmfortqacbffqzocinvuqpjthgekunjsstukeiffjipzzabkuiueqnjgkuiojwbjzfynafnlcaryygqjfixaoeowhkxkbsnpsvnbxuywfxbnuoemxynbtgkqtjvzqikbafjnpbeirxxrohhnjqrbqqzercqcrcswojyylunuevtdhamlkzqnjrzibwckbkiygysuaxpjrgjmurrohkhvjpmwmmtpcszpihcntyivrjplhyrqftghglkvqeidyhtmrlcljngeyaefxnywpfsualufjwnffyqnpitgkkyrbwccqggycrvoocbwsdbftkigrkcbojuwwctknzzmvhbhbfzrqwzllulbabztqnznkqdyoqnrxhwavqhzyzvmmmphzxbikpharseywpfsqyybkynwbdrgfsaxduxojcdqcjuaywzbvdjgjqtoffasiuhvxcaockebkuxpiomqmtvsqhnyxfjceqevqvnapbk"] 82 | for each_test in tests: 83 | print(dynamic_solve(each_test)) 84 | ``` 85 | 86 | ### C 语言版本 1 87 | 88 | 自己用 C 又重写了一遍,期望能通过,结果发现提示说答案错,同样的数据,在网上测试的时候结果错了,在本机测试的时候自己出来的答案是对的。说明不是代码问题,而是题目所给字符串的输入问题,尝试用文件读入数据解决结果发现还是没错,所以就不知道了。以下是代码: 89 | 90 | ```c++ 91 | // 92 | // Created by w@tch on 16/7/21. 93 | // 94 | 95 | #include 96 | #include 97 | 98 | #define MAX_LENGTH 1001 99 | 100 | char *strrev(char *s) { 101 | if (s == NULL || s[0] == '\0') 102 | return s; 103 | 104 | for (char t, *p = s, *q = s + strlen(s) - 1; p < q; p++, q--) { 105 | t = *p; 106 | *p = *q; 107 | *q = t; 108 | } 109 | 110 | return s; 111 | } 112 | 113 | int dynamic_solve(char *s) { 114 | // 先求反串 115 | char *reverse_s = new char(strlen(s) * sizeof(char)); 116 | strcpy(reverse_s, s); 117 | strrev(reverse_s); 118 | 119 | // 初始化 120 | int length = strlen(s); 121 | int i, j; 122 | int dp[MAX_LENGTH][MAX_LENGTH] = {0}; 123 | 124 | // 求最长公共子序列 125 | for (i = 0; i < length; ++i) { 126 | for (j = 0; j < length; ++j) { 127 | if (s[i] == reverse_s[j]) { 128 | dp[i + 1][j + 1] = dp[i][j] + 1; 129 | } 130 | else { 131 | dp[i + 1][j + 1] = dp[i][j + 1] > dp[i + 1][j] ? dp[i][j + 1] : dp[i + 1][j]; 132 | } 133 | } 134 | } 135 | 136 | return length - dp[length][length]; // 长度减去最长公共子序列即为所求 137 | } 138 | 139 | int main(void) { 140 | // FILE *f = fopen("/Users/L1n/Desktop/C_C++ Projects/C_C_Plus_Plus_Knowledge/data.txt", "r"); 141 | FILE *f = fopen("data.txt", "r"); 142 | if (f != NULL) { 143 | char s[MAX_LENGTH] = {0}; 144 | while (fscanf(f, "%s", s) != EOF) { 145 | printf("%d\n", dynamic_solve(s)); 146 | } 147 | } 148 | 149 | 150 | return 0; 151 | } 152 | 153 | /* 提交用 154 | int main() { 155 | char s[MAX_LENGTH] = {0}; 156 | while (scanf("%s", s) != EOF) { 157 | printf("%d\n", dynamic_solve(s)); 158 | } 159 | } 160 | */ 161 | ``` 162 | 163 | ### C 语言版本 2 164 | 165 | 为了通过,照着网上的答案又重新敲了一遍。这回提交正确了,最终代码如下: 166 | 167 | ```C++ 168 | // 构造回文, 解决方案 2, 思路一样都是动态规划, 不过用的库函数不一样 169 | // Created by w@tch on 16/7/23. 170 | #include 171 | #include 172 | #include // reverse, max 函数均位于该头文件中 173 | #include 174 | 175 | using namespace std; 176 | 177 | int main(void) { 178 | string s; 179 | string rs; 180 | while (cin >> s) { 181 | rs = s; // 复制 182 | reverse(rs.begin(), rs.end()); // 逆置 183 | 184 | // 动态规划初始化 185 | int length = s.size(); 186 | vector> lcs(length + 1, vector(length + 1, 0)); 187 | 188 | /* 思路解释 189 | * 两个字符串 BDCABA 和 ABCBDAB, 字符串 BCBA 和 BDAB 都是是它们的最长公共子序列 190 | * lcs[i][j] 表示 s1 长度为 i, s2 长度为 j 时的最大公共子串长度 191 | * 现在已知 lcs[i - 1][j] 即 s1 长度为 i - 1, s2 长度为 j 时的最大公共子串长度 192 | * 而且已知 lcs[i][j - 1] 即 s1 长度为 i, s2 长度为 j - 1 时的最大公共子串长度 193 | * 当 s1 与 s2 同时增加一个字符之后, 判断 lcs[i][j] 的最大公共子串长度 194 | * 动态方程, 如果 s1 和 s2 增加的字符是相同的, 则最大公共子串长度可以 + 1, 否则最大公共子串长度为 lcs[i-1][j] 或 lcs[i][j-1] 195 | */ 196 | for (int i = 1; i <= length; i++) { 197 | for (int j = 1; j <= length; j++) { 198 | if (s[i - 1] == rs[j - 1]) { 199 | lcs[i][j] = lcs[i - 1][j - 1] + 1; 200 | } 201 | else { 202 | lcs[i][j] = max(lcs[i][j - 1], lcs[i - 1][j]); 203 | } 204 | } 205 | } 206 | 207 | cout << length - lcs[length][length] << endl; 208 | } 209 | } 210 | ``` 211 | -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/构造回文/get_longest_palindromic_substring.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | 参考资料: 6 | http://www.cnblogs.com/TenosDoIt/p/3675788.html 7 | 8 | 里面提到了 4 个算法: 9 | 1. 暴力解法,枚举所有子串,对每个子串判断是否为回文,复杂度为O(n^3) 10 | 2. 删除暴力解法中有很多重复的判断。很容易想到动态规划,时间复杂度O(n^2),空间O(n^2),动态规划方程如下: 11 | dp[i][j] 表示子串s[i…j]是否是回文 12 | 初始化:dp[i][i] = true (0 <= i <= n-1); dp[i][i-1] = true (1 <= i <= n-1); 其余的初始化为false 13 | dp[i][j] = (s[i] == s[j] && dp[i+1][j-1] == true) 14 | 在动态规划中保存最长回文的长度及起点即可 15 | 3. 以某个元素为中心,分别计算偶数长度的回文最大长度和奇数长度的回文最大长度。时间复杂度O(n^2),空间O(1) 16 | 4. Manacher算法,时间复杂度O(n), 空间复杂度O(n) 17 | 查看原文链接 18 | """ 19 | 20 | __author__ = '__L1n__w@tch' 21 | 22 | 23 | # 动态规划解决 24 | def dynamic_solve(s): 25 | """ 26 | 动态规划解决, 方程为: 27 | dp[i][j] 表示子串 s[i...j] 是否是回文 28 | 初始化: 29 | dp[i][i] = true (0 <= i <= n - 1) ; dp[i][i - 1] = true (1 <= i <= n - 1); 其余的初始化为 false 30 | 方程: 31 | dp[i][j] = (s[i] == s[j] && dp[i+1][j-1] == true) 32 | 33 | :param s: 34 | :return: 35 | """ 36 | pass 37 | 38 | 39 | # 枚举中心法 40 | def center_enumerate(s): 41 | """ 42 | 以某个元素为中心,分别计算偶数长度的回文最大长度和奇数长度的回文最大长度。时间复杂度O(n^2),空间O(1) 43 | :param s: 待求的字符串 44 | :return: 最大长度 45 | """ 46 | length = len(s) 47 | if length <= 1: 48 | return s 49 | 50 | start, max_length = 0, 0 51 | for i in range(1, length): 52 | # 寻找以 i-1, i 为中点偶数长度的回文 53 | low, high = i - 1, i 54 | while low >= 0 and high < length and s[low] == s[high]: 55 | low -= 1 56 | high += 1 57 | if high - low - 1 > max_length: 58 | max_length = high - low - 1 59 | start = low + 1 60 | 61 | # 寻找以 i 为中心的奇数长度的回文 62 | low, high = i - 1, i + 1 63 | while low >= 0 and high < length and s[low] == s[high]: 64 | low -= 1 65 | high += 1 66 | if high - low - 1 > max_length: 67 | max_length = high - low - 1 68 | start = low + 1 69 | 70 | return s[start:max_length] 71 | 72 | 73 | if __name__ == "__main__": 74 | tests = ["abcda", "google"] 75 | for each_test in tests: 76 | print(center_enumerate(each_test)) 77 | -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/构造回文/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 题目来自于牛客网, 腾讯面试的编程题 3 | 4 | # 原题描述 5 | 给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢? 6 | 7 | 输出需要删除的字符个数。 8 | 9 | 输入描述: 10 | 11 | 输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000. 12 | 13 | 14 | 15 | 输出描述: 16 | 17 | 对于每组数据,输出一个整数,代表最少需要删除的字符个数。 18 | 19 | 输入例子: 20 | 21 | abcda 22 | 23 | google 24 | 25 | 输出例子: 26 | 27 | 2 28 | 29 | 2 30 | 31 | # 最终提交 32 | ```Python 33 | # 这个思路是对的, 但是超时了 34 | import sys 35 | 36 | MAX_LENGTH = 1000 # 1 <= s <= 1000 37 | 38 | 39 | # 答案用动态规划解决的 40 | def dynamic_solve(s): 41 | """ 42 | 动态规划求取构造回文要删除的字符个数 43 | dp[i][j] 表示 s1 的前 i 个字符串, s2 的后 j 个字符串中的最大公共字串 44 | 45 | 动态方程: 46 | dp[i + 1][j + 1] = dp[i][j] + 1 if s1[i] == s2[j] else max(dp[i][j + 1], dp[i + 1][j]) 47 | :param s: 原始字符串 48 | :return: 需要删除的字符个数 49 | """ 50 | length = len(s) 51 | reversed_s = s[::-1] 52 | 53 | # 求最长公共子序列 54 | for i in range(length): 55 | for j in range(length): 56 | if s[i] == reversed_s[j]: 57 | dp[i + 1][j + 1] = dp[i][j] + 1 58 | else: 59 | dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]) 60 | 61 | return length - dp[length][length] # 长度减去最长公共子序列即为所求 62 | 63 | dp = [[0 for i in range(MAX_LENGTH)] for i in range(MAX_LENGTH)] # 初始化 64 | 65 | for line in sys.stdin: 66 | print dynamic_solve(line.strip()) 67 | ``` -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/构造回文/solve.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # version: Python3.X 4 | """ 5 | # 题目描述 6 | 给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?输出需要删除的字符个数。 7 | 8 | # 参考资料 9 | http://www.voidcn.com/blog/Do_Know/article/p-5978576.html 10 | 11 | # 分析 12 | 对于这题来说,插入字符和删除字符使其成为回文串,答案是一样的. 13 | 14 | 首先求s的反串rs,然后对s和rs求最长公共子序列,要删除的字符个数就是 LCS. 15 | """ 16 | 17 | __author__ = '__L1n__w@tch' 18 | 19 | MAX_LENGTH = 1010 # 1 <= s <= 1000 20 | 21 | 22 | # 答案用动态规划解决的 23 | def dynamic_solve(s): 24 | """ 25 | 动态规划求取构造回文要删除的字符个数 26 | dp[i][j] 表示 s1 的前 i 个字符串, s2 的后 j 个字符串中的最大公共字串 27 | 28 | 动态方程: 29 | dp[i + 1][j + 1] = dp[i][j] + 1 if s1[i] == s2[j] else max(dp[i][j + 1], dp[i + 1][j]) 30 | :param s: 原始字符串 31 | :return: 需要删除的字符个数 32 | """ 33 | # 先求反串 34 | length = len(s) 35 | reversed_s = s[::-1] 36 | 37 | # 求最长公共子序列 38 | dp = [[0 for i in range(MAX_LENGTH)] for i in range(MAX_LENGTH)] # 初始化 39 | 40 | for i in range(length): 41 | for j in range(length): 42 | if s[i] == reversed_s[j]: 43 | dp[i + 1][j + 1] = dp[i][j] + 1 44 | else: 45 | dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]) 46 | 47 | return length - dp[length][length] # 长度减去最长公共子序列即为所求 48 | 49 | 50 | if __name__ == "__main__": 51 | tests = ["", "a", "ab", "abcda", "google", 52 | "zgtklhfzomzjckwmluvivvcmhjrwkuvcjrxojobpdedpamdshcwwsetfbacvonecrdvugeibglvhxuymjvoryqjwullvzglqazxrdmczyvbgakjagttrezmvrlptiwoqkrtxuroeqmryzsgokopxxdpbejmtwvpnaqrgqladdszhdwxfckmewhdvihgvacueqhvwvjxoitlpfrckxkuksaqzjpwgoldyhugsacflcdqhifldoaphgdbhaciixouavqxwlghadmfortqacbffqzocinvuqpjthgekunjsstukeiffjipzzabkuiueqnjgkuiojwbjzfynafnlcaryygqjfixaoeowhkxkbsnpsvnbxuywfxbnuoemxynbtgkqtjvzqikbafjnpbeirxxrohhnjqrbqqzercqcrcswojyylunuevtdhamlkzqnjrzibwckbkiygysuaxpjrgjmurrohkhvjpmwmmtpcszpihcntyivrjplhyrqftghglkvqeidyhtmrlcljngeyaefxnywpfsualufjwnffyqnpitgkkyrbwccqggycrvoocbwsdbftkigrkcbojuwwctknzzmvhbhbfzrqwzllulbabztqnznkqdyoqnrxhwavqhzyzvmmmphzxbikpharseywpfsqyybkynwbdrgfsaxduxojcdqcjuaywzbvdjgjqtoffasiuhvxcaockebkuxpiomqmtvsqhnyxfjceqevqvnapbk"] 53 | for each_test in tests: 54 | print(dynamic_solve(each_test)) 55 | -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/算法基础-字符移位.md: -------------------------------------------------------------------------------- 1 | ## 算法基础-字符移位 2 | 3 | ### 题目描述 4 | 5 | 小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。 6 | 你能帮帮小Q吗? 7 | 8 | **输入描述:** 9 | 10 | 输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000. 11 | 12 | 13 | **输出描述:** 14 | 15 | 对于每组数据,输出移位后的字符串。 16 | 17 | **输入例子:** 18 | 19 | AkleBiCeilD 20 | 21 | **输出例子:** 22 | 23 | kleieilABCD 24 | 25 | ### 分析 26 | 27 | 几个知识点: 28 | 29 | * 不需要额外空间的两个数交换操作 30 | * 思路是从后面开始遍历,遇到小写字母就将其与首位交换位置,其余位置依次移位 31 | 32 | ### Python 代码实现 33 | 34 | 最终提交如下: 35 | 36 | ```python 37 | def no_extra_space_swap(a, b): 38 | """ 39 | 不能构建额外空间, 那么交换移动元素使用位操作的那个版本 swap() 40 | 原理是异或了 2 次相当于没有异或 41 | :param a: 'a' 42 | :param b: 'b' 43 | :return: 'b', 'a' 44 | """ 45 | a, b = ord(a), ord(b) 46 | a ^= b 47 | b ^= a 48 | a ^= b 49 | return chr(a), chr(b) 50 | 51 | 52 | def post_order_move(s): 53 | """ 54 | 把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。 55 | :param s: "AkleBiCeilD" 56 | :return: "kleieilABCD" 57 | """ 58 | s = list(s) 59 | last = len(s) - 1 60 | for i in range(last, -1, -1): 61 | if s[i].islower(): 62 | continue 63 | else: 64 | s[i], s[last] = no_extra_space_swap(s[i], s[last]) 65 | for j in range(i, last - 1): 66 | s[j], s[j + 1] = no_extra_space_swap(s[j], s[j + 1]) 67 | last -= 1 68 | 69 | return "".join(s) 70 | 71 | import sys 72 | for line in sys.stdin: 73 | a = line.strip() 74 | print post_order_move(a) 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /腾讯 2017 暑期实习生编程题/腾讯 2017 暑期实习生编程题.md: -------------------------------------------------------------------------------- 1 | # 腾讯 2017 暑期实习生编程题 2 | * 构造回文 3 | * 算法基础-字符移位 -------------------------------------------------------------------------------- /计算机知识/readme.md: -------------------------------------------------------------------------------- 1 | # 题目分布说明 2 | * `1 ~ 75` 题在 `readme1.md` 中 3 | * `75` 题以后在 `readme2.md` 中 --------------------------------------------------------------------------------