字符串去重的再研究
1、前言
今天参加了 某公司的在线笔试,其实题目很简单,一道是关于数组去重,另外一道就是字符串替换的问题。这些问题都是网上很常见的问题,但是答的并不是很理想,如果打分的话只能得到70分,面试官也说我的编程水平中等,这样的评价我是完全认同的。现在就回过头来用多种办法求解这两道题吧。
2、数组去重
方法1:使用hash的方法解决该问题
<span style= "font-size: 14px;" ><strong>2.1.1 初次写出的代码</strong> Array.prototype.unique = function (){ var arr = this , obj = {}, result ,i, len = arr.length; for (i=0 ; i<len; i++){ if (!obj[arr[i]]){ obj[arr[i]] = true ; result.push(arr[i]); } } return result; } </span> |
这是我第一次写的代码,咋一看没什么问题,但是请看下面这个例子
<span style= "font-size: 14px;" > var a = [ 'a' , 'b' , 'a' , 'c' ,3,5,8,3, '8' ] a.unique() // ['a','b','c',3,5,8] </span> |
但是我们期望的结果是什么呢?自然是['a','b','c',3,5,8,'8'],至于什么原因大家都明白。下面是当时我写的很2的方法:
<span style= "font-size: 14px;" ><strong>2.1.2 第一次修bug</strong> Array.prototype.unique= function (){ var arr = this , obj1 = {}, obj2 = {}, result = [], i , len = arr.length; for (i=0; i< len; i++){ if ( typeof arr[i] === 'number' ){ if (!obj1[arr[i]]){ obj1[arr[1]] = true ; result.push(arr[i]); } } else { if (!obj2[arr[i]]){ obj2[arr[i]] = true ; result.push(arr[i]); } } } return result; } var a = [ 'a' , 'b' , 'a' , 'c' ,3,5,8,3, '8' ] var b = a.unique(); //['a','b','c',3,5,8,'8'] </span> |
IQ太低,上面的代码太土,太2,现在想想看还有没有其他办法。
<span style= "font-size: 14px;" ><strong>2.1.3 第二次修bug</strong> Array.prototype.unique= function (){ var arr = this , obj = {}, result = [], i , len = arr.length; for (i=0; i< len; i++){ if (<span style= "color: #ff6600;" >obj[arr[i]] !== arr[i]</span> ){ <span style= "color: #ff6600;" >obj[arr[i]] = arr[i]</span>; result.push(arr[i]); } } return result; } var a = [ 'a' , 'b' , 'a' , 'c' ,3,5,8,3, '8' ]; var b = a.unique(); // ['a','b','c',3,5,8,'8'] </span> |
接下来问题来了,假如存在这样的数组 var a = ['a','b','a','c',3,5,8,3,'8',8];你妈这又出现问题了,结果为['a','b','c',3,5,8,'8',8],那就都存起来:
<span style= "font-size: 14px;" ><strong>2.1.4 第三次修bug</strong> if (!Array.prototype.indexOf){ Array.prototype.indexOf = function (ele,index){ var arr = this , len = arr.length, index = index >= 0 ? index : index + len ,i; for (i=index; i < len; i++){ if (arr[i] === ele){ return i; } } return -1; } } Array.prototype.unique= function (){ var arr = this , obj = {}, result = [], i , len = arr.length; for (i=0; i< len; i++){ obj[arr[i]] = obj[arr[i]] || []; if (obj[arr[i]].indexOf(arr[i]) === -1 ){ <span style= "color: #ff6600;" > obj[arr[i]].push(arr[i])</span>; result.push(arr[i]); } } return result; } var a = [ 'a' , 'b' , 'a' , 'c' ,3,5,8,3, '8' ,8]; var b = a.unique(); // ['a','b','c',3,5,8,'8'] 到目前为止应该不会出现bug了 </span> |
方法2:使用indexOf方法或者lastIndexOf方法
这个方法需要考虑到低版本的浏览器是不知道indexOf属性的,所以使用前非常有必要写下兼容性的代码:
<span style= "font-size: 14px;" > if (!Array.prototype.indexOf){ Array.prototype.indexOf = function (ele,index){ var arr = this , len = arr.length, index = index >= 0 ? index : index + len ,i; for (i=index; i < len; i++){ if (arr[i] === ele){ return i; } } return -1; } } Array.prototype.unique= function (){ var arr = this , obj = {}, result = [], i , len = arr.length , n; for (i=0; i< len; i++){ n = <span style= "color: #ff6600;" >arr.indexOf(arr[i],i+1)</span>; if ( n !== -1){ <span style= "color: #ff6600;" >arr.splice(n,1)</span>; } } return arr; } var a = [ 'a' , 'b' , 'a' , 'c' ,3,5,8,3, '8' ,8]; var b = a.unique(); //['a','b','c',3,5,8,'8']</span> |
现在想出来的也就这两种方法了。
【多线程】在暴力破解中的应用问题---如何避免变量在多线程中冲突(都是调用同一个值)【请各位指点一下!】 - CSDN论坛 - CSDN.NET http://bbs.csdn.net/topics/390603941
TianYi3G2013 - 博客园 http://www.cnblogs.com/TianYi3G2013/
两边同时发,看看哪个社区的更热心~~~~
为方便各位帮忙调试,特附上源码:
Thread.zip_免费高速下载|百度云 网盘-分享无限制 http://pan.baidu.com/s/1zKA4Y
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 using System.Threading; 7 8 9 10 namespace ThreadStu 11 { 12 /// <summary> 13 /// 学习如何避免变量在多线程中冲突(都是调用同一个值) 14 /// 15 /// 【参考】: 16 /// 蜘蛛爬虫多线程控制 - Robin99 - 博客园 17 ///http://www.cnblogs.com/yinhaiming/articles/1533700.html 18 /// 19 /// </summary> 20 class Program 21 { 22 private static int pwd = 321; //假设密码是321(我们一开始并不知道),现在要求利用多线程来暴力穷举它出来; 23 private static int startNum = 1; //假设从1开始穷举 24 private static int count = 0; //穷举次数; 25 26 static void Main(string[] args) 27 { 28 //ThreadStart startCalu = new ThreadStart(calc); 29 //线程开始,即每个线程都执行calc(); 30 //Thread calcThread = new Thread(startCalu); 31 //实例化要开启的新类; 32 //calcThread.Start(); 33 //开启线程; 34 35 36 // 由于线程起始时启动的方法不能带有参数,这就为多线程调用同一个方法添加了麻烦。 37 // 知道开启多线程下载的方法后,大家可能会产生几个疑问: 38 //1. 如何控制线程的数量? 39 //2. 如何防止多线程执行时startNum变量都是从同一数值开始以及如果防止变量count冲突(如线程1的count已经到达98了,线程2实际才10,也跟着结束了。。)? 40 41 //3. 如何控制线程结束? 42 43 44 // 下面就这几个问题提出解决方法: 45 //1. 线程数量我们可以通过for循环来实现 46 47 //比如已知用户指定了n(它是一个int型变量)个线程吧,可以用如下方法开启五个线程 48 49 50 Thread[] calcThread; 51 //声明下载线程,这是C#的优势,即数组初始化时,不需要指定其长度,可以在使用时才指定。这个声明应为类级,这样也就为其它方法控件它们提供了可能: 52 ThreadStart startCalc = new ThreadStart(calc); 53 54 int n = 4; 55 calcThread=new Thread[n]; 56 //为线程申请资源,确定线程总数; 57 58 for (int i = 0; i < n; i++) 59 { 60 calcThread[i] = new Thread(startCalc); 61 //指定线程起始设置; 62 calcThread[i].Start(); 63 //逐个开启线程; 64 } 65 66 67 //2.下面出现的一个问题:所有的线程都调用calc()方法,这样如何避免它们变量startNum都是从相同的数值开始? 68 69 //★ a.这个问题也好解决,只要建立一下startNum地址表,表中的每个地址只允许被一个线程申请即可。 70 71 //具体实现:..不会操作了,请各位帮忙解决! 72 73 74 //★ b.去重问题也可以在C#语言内解决,只根建立一个临时文件(文本就可以),保存所有的startNum地址,差对它们设置相应的属性即可,但查找效率可能不及数据库快。 75 76 77 78 //4.当所有线程任务完成后,通过for循环结束: 79 80 for (int i = 0; i < n; i++) 81 { 82 calcThread[i].Abort(); 83 } 84 85 86 87 Console.ReadLine(); 88 89 } 90 91 //如果要达到在第一个线程中,startNum从1开始 92 // 第二个线程中,.......从100开始 93 // 第三个线程,.........从200开始 94 // 第四个线程,.........从300.... 95 96 97 //这个startNum的值可以保存在一个文本文件中,只要能达到避免线程冲突就可以了: 98 static void calc() 99 { 100 while (count < 100) //当一个线程把变量startNum累加100次(如果避免这个count变量线程冲突??)后停止; 101 { 102 if (startNum != pwd) 103 { 104 startNum++; 105 } 106 else 107 { 108 109 110 111 //xxxxxxxxxxxxxxxxxxxxxxxxxxxx 112 //当穷举正确后,停止所有线程; 113 Console.WriteLine(startNum); 114 Console.ReadLine(); 115 } 116 count++; 117 } 118 119 } 120 121 122 123 } 124 }