Algorithmjava
今天的算法題目是「存在重複元素」,從今天這道簡單的算法題中,被折磨的死去活來的,不知道從何下手,只會最簡單的遍歷,結果是報了超時了。隨後,本身思考了一陣,發現有官方題解,去裏面尋找了一下解體思路,一會兒明朗起來。也發現了本身對於理論的不足!git
Review程序員
今日閱讀文章:「Regex tutorial — A quick cheatsheet by examples」正則表達式
關於正則表達式的:算法
總結:從中又再次複習了正則表達式的一些內容,由於英文的緣故,後面的一些有點理解有點吃力,基礎部分的語法獲得了複習,從此要繼續增強對正則表達式的練習。sql
Tipexpress
今天的tips就分享我本身寫的經典快速排序吧(Java 8 默認的sort方法的排序性能已經很高了),按照其餘人再加上本身的理解寫出來的(性能仍是有待提高的),若是有錯誤,還請你們幫忙糾正,編程
基於Java編寫的:後端
public static void quickSort(int[] arr, int left, int right) {
if (right - left > 0) {
int left1 = left;
int right1 = right;
int pivot = arr[left];
while(left1 <= right1) {
while (pivot > arr[left1]) {
++ left1;
}
while(pivot < arr[right1]) {
-- right1;
}
if (left1 <= right1) {
if (left1 == right1) {
arr[left] = arr[right1];
arr[right1] = pivot;
} else {
int temp = arr[right1];
arr[right1] = arr[left1];
arr[left1] = temp;
}
++ left1;
-- right1;
}
}
if (left < right1) {
quickSort(arr, left, right1);
}
if (left1 < right) {
quickSort(arr, left1, right);
}
}
}
複製代碼
Shareapi
這是一篇關於快速排序的文章,由於今天的算法題,有考到關於排序的要點,因此本身就去檢索了幾篇關於快速排序的文章,這篇我認爲是比較好的,也讓我今天對快速排序有了更深的認識(我算法基礎不好的)。但願也能夠幫助到其餘人!
Algorithm 本週算法:136.只出現一次的數字 此次算法題由於受第一週算法的影響,以及它的題目描述中的「你能夠不使用額外空間來實現嗎?」,因而我就採用了排序加循環比較的方式。 個人題解思路:首先,先讓數組進行排序,排序完後,進行循環比較,在每次循環開始前,我會設置一個值爲false的Boolean標記,從索引0開始,將相鄰的兩個數同中間的一個數比較,若是相同將標記置爲false,若是不一樣將標記置爲true。在單次循環的最後判斷標記,若是爲true,則爲答案,若是爲false則繼續循環。在這裏要注意兩個臨界值,首先是索引0的左邊界值,及索引爲length - 1的右邊界值。
Review 本週閱讀文章:「The Key To Accelerating Your Coding Skills」 這篇文章主要講述了,在學習編程的過程當中,若是去快速的經過本身編程的拐點,經過這個拐點以後,自身的變成技能將會獲得質的提高,可是在這個階段時,會經歷不少讓你以爲很艱難的事情,甚至讓你想放棄,但只要堅持下來,就必定能夠經過的。
Tip 受本週算法的影響,我發現了二進制數真的很神奇,我本身的題解耗時9ms,可是使用二進制的異或運算居然僅僅花費1ms。可是細想,這也合情合理,畢竟計算機自己就是二進制,這就是計算機最擅長的事情啊。 0異或任何數=任何數 1異或任何數-任何數取反 任何數異或本身=把本身置0
Share 啓發很大,必須分享! The Key To Accelerating Your Coding Skills
Algorithm 本週LeetCode 題目:350. 兩個數組的交集 II 題解思路:首先,將兩個數組進行排序。比較兩個數組的長度,將長度較小的那個放在外層循環,長度較長的放在內層循環,這樣的作法是能夠減小檢索的次數,當數組長度相差極大的時候,這種方式的優勢就能夠凸顯。隨後,進行遍歷獲取交集,假設剛開始的前n次遍歷沒有找到相等的數字,則下次遍歷還會從0索引開始。若是在前n次遍歷中,在第n次遍歷,找到相等項,處理以後結束內層循環,則第n+1次會在第n次的索引i+1 處的地方繼續進行遍歷,這樣得益於排序以後的好處。 題解代碼:
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
List<Integer> result = new ArrayList<>();
int start = 0;
if(nums1.length <= nums2.length) {
for (int i = 0; i < nums1.length; i++) {
int find = nums1[i];
for (int j = start; j < nums2.length; j++) {
if (find == nums2[j]) {
result.add(Integer.valueOf(find));
start = j + 1;
break;
}
}
}
} else {
for (int i = 0; i < nums2.length; i++) {
int find = nums2[i];
for (int j = start; j < nums1.length; j++) {
if (find == nums1[j]) {
result.add(Integer.valueOf(find));
start = j + 1;
break;
}
}
}
}
int[] nums3 = new int[result.size()];
for (int i = 0; i < result.size(); i++) {
nums3[i] = result.get(i);
}
return nums3;
}
}
複製代碼
Review 本週文章:Why you should totally switch to Kotlin 我的看法;我本身的主語言是Java,這篇文章表達了許多有關於Kotlin這門編程語言的好處,的確有挺多解決Java語言以前的痛點的(我的基於JDK 8來闡述),好比兩個對象的數據都相等的話,咱們在現實生活中就會認爲這兩個對象是相等的,而在Java的語法中,在默認的equals方法,由於這兩個對象所存放的內存地址是不一樣的,因此就會返回false,因此會讓Java程序員重寫了equals方法,可是在Kotlin中提供了==和===比較符,==只要數據相同就會返回true,而===的結果同默認的equals方法。這樣省去了重複性的編碼,可是Kotlin雖然是簡化Java的代碼風格,可是我的感受語法風格上仍是有些彆扭,給個人感受是基於Java和Python中間,Python的語法是真的讓我感受很簡潔明瞭。
Tip 本週Tip:在Java中,方法的調用永遠是值調用,而不像C++,Python有引用調用及值調用(基於JDK 8)
Share 最近迷上了一部美劇叫Stranger Things,中文譯名:怪奇物語,很是好看。能夠用來學習英語。
Algorithm 本週題目:66.加一 題解思路:本道題目總共分爲兩種常規狀況,和一種臨界狀況。 1.常規狀況一:數組末位值加一,不發生進位,直接將末位值加一,返回數組便可。這是最簡單的狀況 2.常規狀況二:數組末位值加一,發生進位,從本道題目來說,發生進位的狀況只有當前數組爲9,當發生進位後,本位上的數值一定爲0,進位後須要繼續遍歷該數組,移動當前索引減一,繼續執行以上操做,如若繼續發生進位,則繼續如上操做,反之結束遍歷,返回數組結果。 3.臨界狀況:此爲常規狀況二的臨界狀況,當數組元素全爲9時,一定發生數組長度擴大一位,若是最後一次遍歷時,發生進位狀況,則出發此臨界狀況處理代碼:數組長度擴大一位,首位填入1,其他用0填充,返回該構造數組。 題解代碼:
class Solution {
public int[] plusOne(int[] digits) {
int begin = digits[digits.length - 1] + 1;
if (begin > 9) {
for (int i = digits.length - 1; i >= 0; i--) {
int flag = digits[i] + 1;
if (flag > 9) {
digits[i] = 0;
if (i == 0) {
int[] result = new int[digits.length + 1];
result[0] = 1;
for (int j = 1; j < digits.length; j++) {
result[j] = 0;
}
return result;
}
} else {
digits[i] = digits[i] + 1;
break;
}
}
} else {
digits[digits.length - 1] = digits[digits.length - 1] + 1;
}
return digits;
}
}
複製代碼
Review lambda表達式基礎入門 這是一篇關於Lambda的基礎用法的簡介,Lambda表達式是Java8的重大變化之一,它的到來讓Java進入了函數式編程的領域,使用更簡潔的代碼,完成更多的功能,同時也增長代碼的靈活性,讓程序員從冗餘的代碼塊中解放出來。在我查找Lambda表達式的文章的時候,我發現了一篇關於講述Lambda表達式讓代碼變慢的說法,我我的不贊同這種說法,首先Lambda是Java以後發展的方向選擇,及時在一些特殊的狀況下,的確會變慢一些些,可是這也須要業務場景的加持,在可接受的範圍內就是OK的。以後,學到了較爲底層的時候,我就會去研究對應的場景,看是否變慢。
Tip Spring 的 AOP機制,是基於Java的代理機制,Spring用了更爲強大的框架CGLIB。
Share lambda表達式基礎入門 這是一篇介紹關於Lambda的基礎用法
Algorithm 本週題目:283.移動零 解題思路:今天這道題目耗費了三個半小時還沒解出來,由於一開始的思路錯誤了,致使一直在死衚衕裏面鑽,以後要給本身解題設置時間限制,最多45分鐘,若是沒解出來就要去看別人的題解思路了。今天的這道題,我一直用二分查找的思想在想這道題,可是一直行不通,錯了四次,而後我看了題解思路以後,豁然開朗,原來這道題的思路這麼簡單,我卻花費了這麼久還沒解出來!!以後在解題的時候要多多轉換思路,不能一直蒙着頭一直往前衝。官方的題解思路是:這道題目能夠分爲兩個子問題進行,1.不爲0的數字移動至前面,2移動完成後在最後一位不爲0的數字後的索引填充0。這樣簡單用幾行代碼就能夠完成這道題目了。我用了數十行代碼還沒解決。 題解代碼:
class Solution {
public void moveZeroes(int[] nums) {
int indexNotZero = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
nums[indexNotZero] = nums[i];
indexNotZero++;
}
}
for(int i = indexNotZero; i< nums.length; i++) {
nums[i] = 0;
}
}
}
複製代碼
Review What I learned from doing 1000 code reviews 這篇文章告訴咱們如何在編碼中改掉一些壞習慣
Tip 編碼思路:經過拆解功能模塊爲若干個子問題,將關注點移至某子問題上,而不受其餘子問題的困擾。我在這種開發模式上獲益很大,在逐一解決子問題的過程當中,我發現我格外的輕鬆。考慮的方面僅僅只是子問題的部分,其餘的子問題對我來講是不可見的,我是根本不用去考慮,子問題封裝的方法,我在另外一個子問題還能夠複用,一箭雙鵰。跟我以前面對大問題去編碼的狀況有着質同樣的變化。那時候我考慮這個考慮那個,最後把本身擰成了一團麻,不只耗費時間,並且問題還得不到完善的解決。因此在面對一個模塊,或者一個功能的時候,必定要三思然後行,將模塊的需求,及主要的狀況,以及面對臨界值的考慮思考清楚,頭腦中有了成型的思路之後,編碼的速度奇快無比,並且還很輕鬆,千萬不能一股腦的就立馬開始敲代碼。
Share 修改tomcat端口方法 讓服務器能夠啓動多個tomcat
Algorithm 本週算法題:1. 兩數之和 題解思路:我在剛接觸到這道題目的時候,又陷入了一種錯誤的思路中:把數組先進行排序... 這是多麼錯誤的思路,出現這樣的低級錯誤應該歸根於個人算法基礎薄弱,以及邏輯思惟不夠發散,每每會侷限於一種解法中。缺乏觸類旁通的能力,從此仍是要多看書,寫做,多多編寫算法題以及進行思考。從各類不一樣的方面去思考。迴歸正題,因而我花費了半個小時的時間,在錯誤的思路中解題,結果,意料之中的沒有解決。在上週的作題經歷中吸收的教訓,我從新轉換了思路。因而,發現了新的解題思路,但也是最最最普通的題解思路:雙重循環遍歷。細節在這裏,我就不進行概述了,你們應該都明白。在二刷的時候,我會回來的!!! Review How to write a good software design doc 這篇文章講訴如何去編寫一篇軟件設計文檔,文章內容分爲了四個部分: 1.爲何要編寫設計文檔 2.設計文檔中須要包含什麼 3.怎麼樣去編寫一篇設計文檔 4.設計文檔的整體流程是什麼 一篇好的設計文檔決定了一個項目的開頭的好壞,若是在項目初期,對於項目的準備工做以及其相關的文檔十分重視,那麼這個項目在起點,就已經超過不少項目了,設計文檔也是其中的一部分,它避免了開發人員去作一些錯誤的解決方案,大多數錯誤的解決方案在考慮設計項目架構的時候均可以被避免。然而一些公司不重視項目初期的構建 ,在項目後期,將會承受高返工率帶來的巨大損失!製做軟件產品也是一門手藝活,它須要開發團隊去精雕細琢,而不是像快餐式的開發模式去對待,對本身開發產品付出的努力終將獲得相對應的回報!
Tip 編碼小貼士:信息隱藏。今天在《代碼大全2》中閱讀到這一部分,在這裏簡述個人思路:信息隱藏在程序設計中擁有相當重要的位置,它是做爲面向對象設計原則的根基,例如,我如今所學習的Java語言中的一大特性——封裝,就是這一原則的體現。信息隱藏能夠下降類與類之間的耦合度,類把複雜的實現細節隱藏在類的內部,調用類無須知道其實現原理,當服務類修改內部的實現細節,其調用者將毫無察覺。信息隱藏能夠將多變系統部分,固定在區域性的範圍內,下降需求的變化對系統形成的影響。信息隱藏能夠提升程序的伸縮性,將對應變化的部分隱藏至一個類或多個協做類中,如系統的硬件支持變化,只需更改對應類中的實現,實現改動量最小化,靈活性最大化!
Share 騰訊雲入門中心 騰訊雲入門中內心面有許多免費的教程,好比,如何搭建LAMP環境,Nginx環境等等,一些開發經常使用的環境。裏面的教程相對於搜索引擎上我的編寫的教程來講,仍是比較清楚的。步驟詳細,照着步驟去搭建,通常是不會出問題的。我我的以前搭建環境的時候,都是使用搜索引擎進行搜索,對各個搜索結果進行嘗試,其中不乏有搭建失敗,步驟模糊或者部署環境配置錯誤,所以花費了許多時間排錯,這是很是惋惜的。因此,在這裏分享一下我現階段的思路:首先,登錄對應的官網查找搭建文檔,官網上都有對應的文檔說明,可是諸如後端的主流開源框架,大部分都是英文的搭建文檔,少部分提供中文(英文基礎較差的同窗要加緊了,包括我本身),照着官網文檔搭建百分之九十九都會成功的。其次,就是登錄以上推薦的網站,查看是否有對應的教程。最後,若是以上兩種都無論用的話,那就啓動面向搜索引擎的模式吧!
Algorithm 本週算法:36.有效的數獨 題解思路:首先這道題目我沒有自行解決,第一次遇到中等難度的題目,就被圍困半小時了結。因而我查閱了官方題解,它使用了27個HashMap做爲存儲集合,每行,每列,每一個框各有一個HashMap,對於我來講比較有難度的地方爲,它使用了一個轉換公式將每一個框的索引肯定,該轉換公式爲:
int boxIndex = (i / 3) * 3 + j / 3;
複製代碼
隨後開始遍歷整個二維char數組,使用Hash表的特性進行判斷。
題解代碼:
class Solution {
public boolean isValidSudoku(char[][] board) {
// init data
HashMap<Integer, Integer> [] rows = new HashMap[9];
HashMap<Integer, Integer>[] columns = new HashMap[9];
HashMap<Integer, Integer> [] boxes = new HashMap[9];
for (int i = 0; i < 9; i++) {
rows[i] = new HashMap<Integer, Integer>();
columns[i] = new HashMap<Integer, Integer>();
boxes[i] = new HashMap<Integer, Integer>();
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int num = (int)board[i][j];
if (num != '.') {
int boxIndex = (i / 3) * 3 + j / 3;
rows[i].put(num, rows[i].getOrDefault(num, 0) + 1);
columns[j].put(num, columns[j].getOrDefault(num, 0) + 1);
boxes[boxIndex].put(num, boxes[boxIndex].getOrDefault(num, 0) + 1);
if (rows[i].get(num) > 1 || columns[j].get(num) > 1 || boxes[boxIndex].get(num) > 1) {
return false;
}
}
}
}
return true;
}
}
複製代碼
Review The Decorator Pattern — A simple guide 這邊文章主要是介紹裝飾器模式的一些用法
Tip 這是我收集的Linux 命令行的用法 1.find usage Use find from the command line to locate a specific file by name or extension. The following example searches for .err files in the /home/username/ directory and all sub-directories: find /home/username/ -name ".err"
Share 分享一篇我本身編寫的 elasticdump使用方法入門
Algorithm 本週算法:48.旋轉圖像(未解出) 題解思路:使用兩次翻轉來實現旋轉效果,首先第一次翻轉,將對應的行數字移動至它旋轉後應在的數組中,可是位置並不必定正確,好比7原先在索引爲2的數組,經過翻轉將它移動至索引爲0的數組中。第二次翻轉則將每一個一維數組進行反轉操做,將對應數字移動到正確的位置。
題解代碼
class Solution {
public void rotate(int[][] matrix) {
int n = matrix.length;
for (int i = 0; i < n; i ++) {
for (int j = i; j < n; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
for (int i = 0; i < n; i ++) {
for (int j = 0; j < n / 2; j++) {
int tmp = matrix[i][j];
matrix[i][j] = matrix[i][n - j - 1];
matrix[i][n - j - 1] = tmp;
}
}
}
}
複製代碼
Review 略
Tip 如下是關於cp命令的使用 cp usage \cp -rf file1.txt file2.txt cp前加上\ 在存在相同文件時,進行覆蓋而不提示 -r -R Copy directories recursively. 遞歸複製文件及文件夾 -f If an existing destination file cannot be opened, remove it and try again. This option has no effect if the -n/--no-clobber option is used. However, it applies independently of -i/--interactive; neither option cancels the effect of the other,若是目標文件存在,強制將其刪除,並從新執行復制操做。
Share 這是一篇關於FTP服務器安裝的過程,我已根據這篇文章成功搭建出對應的FTP服務器。 ftp安裝
Algorithm 344. 反轉字符串 題解思路:採用二分法的思想,將整個數組一分爲二,使用中間變量,由外向內的進行首位與末位的循環替換。 題解代碼:
class Solution {
public void reverseString(char[] s) {
int length = s.length;
for (int i = 0; i < length / 2; i++) {
char temp = s[i];
s[i] = s[length - i - 1];
s[length - i - 1] = temp;
}
}
}
複製代碼
Review
Callback Functions in JavaScript
這是關於JavaScript(如下簡稱爲JS)回調函數的相關概念 1.JS中定義的函數能夠傳遞代碼塊,隨後在函數內部執行對應的函數 2.JS在函數體內部必定要判斷做爲回調函數參數的類型,由於JS是一種弱類型的語言,不像Java在定義參數的時候須要指定參數的類型,因此必定要作好參數檢查的工做。 3.在函數體內部若是調用了異步函數,須要確認該異步函數與回調函數是否存在調用的順序問題,若是存在,有一種解決方案:直接將回調函數放置異步函數的末尾。由於回調函數,極有可能在異步函數以前執行完畢。
Tip 在JS中應該避免使用var關鍵字變量,更改成let關鍵字定義變量,let 具備比var更爲嚴格的語法要求,也是JS官方推薦使用。
Share 推薦MDN的JS學習指南,國慶後三天都在學習有關於JS方面的基礎知識,準備學習好基礎知識後去學習Vue.js框架,爲正式入門的做業打下基礎。
Algorithm 7.整數反轉
題解代碼
if (x == Integer.MAX_VALUE || x == Integer.MIN_VALUE) {
return 0;
}
StringBuilder stringBuilder = new StringBuilder(String.valueOf(Math.abs(x)));
long l = Long.parseLong(stringBuilder.reverse().toString());
if (l > Integer.MAX_VALUE) {
return 0;
}
if (x > 0) {
return (int)l;
} else {
return (int)l * -1;
}
複製代碼
題解思路:
首先進行判斷傳入參數的大小是否等於整數範圍的最大值或者最小值,如若如此,則直接進行返回0。接着將參數的絕對值進行字符化,反轉以後轉化爲long類型整數,將此與Integer的最大值進行比較,若是大於則返回0。若是符合轉換要求。對參數的正負性進行判斷。爲負數時乘以-1。 Review RESTful API Design - Step by Step Guide
這篇文章主要談論關於Restful API的設計準則,我閱讀完這篇文章後,我的受到了極大的啓發,糾正了我在以前工做時對於Restful API設計的錯誤觀念。
1.RESTful API的命名規則儘可能要簡單而且能凸顯提供的接口的功能性。在此以前,我對於API的命名主要以get爲前綴開頭,List爲後綴結尾爲主,伴隨着中間一系列的動詞及名詞來代表此接口方法的功能性。這也是做者所提出的常見錯誤之一,好比關於產品方面的列表查詢,我一般會使用productList,獲取單一的產品,我會使用getProductById,雖然也能具體代表API的功能性,可是卻帶來了十分冗餘的接口命名。而做者僅僅使用了products及products/id代表了我所須要接口的定義,卻帶來了及其簡單的接口命名。
2.RESTful API須要版本控制。這一點再一次震撼到我,由於在我目前的工做生涯中,我歷來都不知道RESTful API是須要進行版本控制的,個人一般作法是直接在當前版本上進行修改,若是變更過大,將致使調用者的代碼報錯,而且沒有足夠的時間去調整。
Tip Ubuntu 切換root用戶不使用密碼 sudo su - root
Share 今天分享的是Openstack的官方API文檔,由於公司近期作的項目有設計虛擬化,因此本身也就在接觸這方面的文檔。可是Openstack的官方文檔真的是很是的多。看完須要必定量的時間。本來想本身搭建一套Openstack的環境。結果被各類錯誤折磨的煩不勝煩,花費了7天時間。仍是沒有搭建出來,最後不得已放棄了,由於本身的進度計劃上還有更重要的事情要完成。
Algorithm 字符串中的第一個惟一字符
題解代碼:
public int firstUniqChar(String s) {
HashMap<Character, Integer> count = new HashMap<Character, Integer>();
int n = s.length();
// build hash map : character and how often it appears
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
count.put(c, count.getOrDefault(c, 0) + 1);
}
// find the index
for (int i = 0; i < n; i++) {
if (count.get(s.charAt(i)) == 1)
return i;
}
return -1;
}
複製代碼
題解思路:
根據題目就能夠獲得使用Hash表數據結構去解題,使用兩個for循環,第一個for循環統計字符串中各個字符出現的次數,第二個for循環從新遍歷整個字符串,若獲得字符的次數爲1,則這個字符爲第一個惟一的字符,返回其index。若整個字符串都沒有惟一,則返回-1.
Review 本週閱讀OpenStack官方文檔,OpenStack做爲雲計算時代的主力之一,着實讓人佩服。從剛開始接觸OpenStack時(也就在兩週前),那時它對我來講是濛濛朧朧的。在通過這兩週的研究,發現網上的資料參次不齊,大多數都過期了。因此我就直接去啃官網的英文文檔了,官方的文檔十分完善,因此要接觸或者學習OpenStack的同窗們,不要去百度找中文資料,直接上官網查閱英文資料。在通過「痛苦」的兩週後,這周開始封裝OpenStack的Keystone client以及glance client。
Tip 根據OpenStack glance rest api用來建立鏡像,建立完後,只是一條記錄,這條記錄的狀態顯示排隊中,須要另外上傳鏡像文件。
Share docs.openstack.org/train/
Algorithm
892.三維形體的表面積
題解思路:每一個正方形方格中疊放的正方體,底部和頂部兩面一定暴露,不存在其餘方格中遮擋狀況,剩下東西南北四面,判斷是否有正方體存在,若是有則減去對應的遮擋面積,反之加上全面積。以此遍歷每一個方格,加上後則爲總表面積。
題解代碼:
class Solution {
public int surfaceArea(int[][] grid) {
// setting four direction
int[] dc = new int[] {0, 0, 1, -1};
int[] dt = new int[] {1, -1, 0, 0};
int N = grid.length;
int total = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int v = grid[i][j];
if (v > 0) {
total += 2;
for (int l = 0; l < 4; l++) {
int k = i + dc[l];
int h = j + dt[l];
int nv = 0;
if (0 <= k && k < N && 0 <= h && h < N) {
nv = grid[k][h];
}
total += Math.max(v - nv, 0);
}
}
}
}
return total;
}
}
複製代碼
1114.按序打印
題解思路:採用Java關鍵字synchronized,用來控制線程打印的優先級,經過優先級高低依次獲取鎖,執行線程任務,隨後再釋放鎖,喚醒等待線程。
題解代碼:
class Foo {
public boolean firstFinished = false;
public boolean secondFinished = false;
public Object lock = new Object();
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
synchronized(lock) {
printFirst.run();
firstFinished = true;
lock.notifyAll();
}
}
public void second(Runnable printSecond) throws InterruptedException {
// printSecond.run() outputs "second". Do not change or remove this line.
synchronized(lock) {
while(!firstFinished) {
lock.wait();
}
printSecond.run();
secondFinished = true;
lock.notifyAll();
}
}
public void third(Runnable printThird) throws InterruptedException {
// printThird.run() outputs "third". Do not change or remove this line.
synchronized(lock) {
while(!secondFinished) {
lock.wait();
}
printThird.run();
}
}
}
複製代碼
443.壓縮字符串
思路:採用遍歷,在遍歷的過程當中比對字符的是否相等,而且統計相等字符的次數,這其中採用兩種方式去處理相等字符及不相等狀況。相等狀況則sum加上1。不相等狀況,sum若是大於1,則將sum轉換爲字符串,判斷長度,遍歷放入原數組中。最後處理最後一個字符串的臨界值狀況。
代碼:
class Solution {
public int compress(char[] chars) {
int len = 0;
int sum = 0;
char original = chars[0];
int j = 0;
for (int i = 0; i < chars.length; i++) {
char cha = chars[i];
if (cha == original) {
sum += 1;
} else {
len += 1;
chars[j++] = chars[i - 1];
if (sum > 1) {
String numStr = String.valueOf(sum);
len += numStr.length();
for (int k = 0; k < numStr.length(); k++) {
chars[j++] = numStr.charAt(k);
}
}
original = cha;
sum = 1;
}
}
len += 1;
chars[j++] = chars[chars.length - 1];
if (sum > 1) {
String numStr = String.valueOf(sum);
len += numStr.length();
for (int k = 0; k < numStr.length(); k++) {
chars[j++] = numStr.charAt(k);
}
}
return len;
}
}
複製代碼
53.最大子序和
思路:採用動態規劃,遍歷數組,若是sum大於0,則繼續該次連續加法,若是sum 不大於0,則意味該次連續加法已不是最大和,重置連續加法,將sum至爲當前的數字,每次加法操做,sum最後都須要與ans作比較。ans當前存放着連續的最大和,遍歷結束後,ans裏則爲連續的最大和
代碼:
class Solution {
public int maxSubArray(int[] nums) {
int ans = nums[0];
int sum = 0;
for (int num : nums) {
if (sum > 0) {
sum += num;
} else {
sum = num;
}
ans = Math.max(ans, sum);
}
return ans;
}
}
複製代碼
206.反轉鏈表
思路:採用遍歷的方式,將鏈表的每一個節點的的下一個節點指向上一個節點,返回最後的引用
代碼:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while(curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
}
複製代碼
Review
Elasticsearch user auth
根據ES官方文檔,ES的Xpack鑑權框架在6.8以前是須要收費,我將ES版本從6.5更新至6.8,沒有發生任何不兼容的問題。6.8後的Xpach免費提供了基礎的鑑權服務,對於普通的使用者而言,已經足夠使用。
Tip
Previous operation has not finished; run 'cleanup' if it was interrupted
執行 sqlite3 .svn/wc.db "delete from work_queue". 把隊列清空。
執行 sqlite3 .svn/wc.db "select * from work_queue".\ 確認一下是否已經清空隊列,發現已經沒有記錄顯示,說明已經清空了。
最後嘗試svn cleanup。
Share
SVN fail to cleanup
Algorithm
415.字符串相加
思路:採用遍歷迭代,經過遍歷兩個字符串的各個字符位,將相對應的字符位進行相加操做,而且加上進位,處理相加和的價位,將剩下的值轉換爲字符串加入到StringBulider中,當遍歷完成後,進行反轉操做,便可獲得最終的值。這裏使用了一個小技巧,就是在代碼num1.charAt(i) - '0'中,由於數字的字符減去0字符,便可獲得它自己的整數值,根據ASCII表中的值來定義的。
代碼:
class Solution {
public String addStrings(String num1, String num2) {
StringBuilder sb = new StringBuilder();
int i = num1.length() - 1;
int j = num2.length() - 1;
int carry = 0;
while(i >= 0 || j >= 0 ) {
int k = i >= 0 ? num1.charAt(i) - '0' : 0;
int h = j >= 0 ? num2.charAt(j) - '0' : 0;
int temp = k + h + carry;
carry = temp / 10;
sb.append(String.valueOf(temp % 10));
i--;
j--;
}
if(carry == 1) {
sb.append(carry);
}
return sb.reverse().toString();
}
}
複製代碼