感觉以下几个小问题有点意思,有些代码是自己写的,有些则是总结别人或者引用别人的,代码可能有些不足或者其他解法以及优化,欢迎指出,一起进步。
/**
* 问题描述:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
* 思路:使用set,如果集合中存在该元素则删除,否则加入,最后元素只会剩下只出现一次的元素,得到结果。
*/
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < array.length; i++){
//包含则删除
if (set.contains(array[i])){
set.remove(array[i]);
}else {
set.add(array[i]);
}
}
Integer[] temp = new Integer[2];
set.toArray(temp);
num1[0] = temp[0];
num2[0] = temp[1];
}
/**
* 获得两个整形二进制表达位数不同的数量。
* @param m 整数m
* @param n 整数n
* @return 整型
*/
public int countBitDiff(int m, int n){
//先进行异或处理,然后0替换掉,判断长度
String string = Integer.toBinaryString(m^n);
string = string.replace("0", "");
return string.length();
}
/**
* 输入两个链表,找出它们的第一个公共结点。
* 思路:遍历第一个链表并将值保存在map中,其次遍历第二条链表,判断该值是否存在map中,存在则返回。
* @param pHead1
* @param pHead2
* @return ListNode
*/
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode currentOne = pHead1;
ListNode currentTwo = pHead2;
Map<ListNode, Integer> map = new HashMap<ListNode, Integer>();
while (currentOne != null){
//存入map
map.put(currentOne, null);
currentOne = currentOne.next;
}
while (currentTwo != null){
//存在则返回第一个节点
if (map.containsKey(currentTwo)){
return currentTwo;
}else {
currentTwo = currentTwo.next;
}
}
return null;
}
/**
* 问题描述:假设一个球从任意高度自由落下,每次落地后反跳回原高度的一半;
* 再落下, 求它在第5次落地时,共经历多少米?第5次反弹多高?
*/
public static void getJourney(int high)
{
double back = high;
double sum = high;
for(int i = 0; i < 5; i++){
sum += back;
back = back/2;
}
System.out.println(sum);
System.out.println(back);
}
/**
* 将一个字符中所有出现的数字前后加上符号“*”,其他字符保持不变。
* 思路:在数字前后都加上*,最后将**替换掉。(看牛友的,感觉思路很棒)
*/
public static String MarkNum(String pInStr)
{
StringBuffer stringBuffer = new StringBuffer();
for(int i = 0; i < pInStr.length(); i++){
if (pInStr.charAt(i) >= 48 && pInStr.charAt(i) <= 57){
stringBuffer.append("*" + pInStr.charAt(i) + "*");
}else {
stringBuffer.append(pInStr.charAt(i));
}
}
System.out.println(stringBuffer.toString());
return stringBuffer.toString().replace("**", "");
}
/**
* 找出字符串中第一个只出现一次的字符,
* 输出第一个只出现一次的字符,如果不存在输出-1。
* 思路:使用map将字符作为key,出现次数作为value,很多字符串的题都可以这样做。
*/
public static void PrintSingleChar(String string){
Map<Character, Integer> map = new HashMap<Character, Integer>();
for (int i = 0; i < string.length(); i++){
if (map.containsKey(string.charAt(i))){
//存在则次数加1
map.put(string.charAt(i), map.get(string.charAt(i))+1);
}else {
//不存在则value=1
map.put(string.charAt(i), 1);
}
}
for (int i = 0; i < string.length(); i++){
if (map.get(string.charAt(i)) == 1){
System.out.println(string.charAt(i));
return;
}
}
System.out.println("-1");
}
/**
* 输入一个链表,输出该链表中倒数第k个结点。
* 思路:存入栈中,弹出k-1个数后返回k个。
* 注意:栈不能为空,栈长度大等于k,k大于0,否则都返回null。
*/
public ListNode FindKthToTail(ListNode head,int k) {
ListNode temp = head;
Stack<ListNode> stack = new Stack<ListNode>();
//直接遍历入栈
while (temp != null){
stack.push(temp);
temp = temp.next;
}
if (!stack.isEmpty() && stack.size() >= k && k > 0){
for (int i = k-1; i > 0; i--){
stack.pop();
}
return stack.pop();
}else {
return null;
}
}
/**
* 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?
* 为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,
* 但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,
* 可以很快的求出任意非负整数区间中1出现的次数。
* 思路:转存字符串数组,遍历。
*/
public static int NumberOf1Between1AndN_Solution(int n) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i <= n; i++){
stringBuffer.append(i);
}
int count = 0;
for (int i = 0; i < stringBuffer.length(); i++){
if(stringBuffer.charAt(i) == '1'){
count++;
}
}
return count;
}
/**
* 统计一个数字在排序数组中出现的次数。
* 思路:二分法(看到牛友的解答,感觉很棒),不过必须在顺序从小到大的情况下。
*/
public static int GetNumberOfK(int [] array , int k) {
int start = GetLower(array, k);
int end = GetUper(array, k);
return end - start + 1;
}
//获取k第一次出现的下标
public static int GetLower(int [] array , int k){
int start = 0;
int end = array.length-1;
int mid = (start + end)/2;
while (start <= end){
if (array[mid] < k){
start = mid + 1;
}else {
end = mid - 1;
}
mid = (start + end)/2;
}
return start;
}
//获取k最后一次出现的下标
public static int GetUper(int[] array, int k){
int start = 0;
int end = array.length-1;
int mid = (start + end)/2;
while (start <= end){
if (array[mid] <= k){
start = mid + 1;
}else {
end = mid - 1;
}
mid = (start + end)/2;
}
return end;
}
/**
* 一个链表中包含环,请找出该链表的环的入口结点。
* 思路:要寻找环的入口节点,遍历节点的时候,遇到的第一个重复节点肯定入环节点,
* 所以定义一个Set,添加失败时即返回入口节点
*/
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if (pHead == null){
return null;
}else {
Set<Integer> set = new HashSet<Integer>();
ListNode listNode = pHead;
while (listNode != null){
if(!set.add(listNode.val)){
return listNode;
}
listNode = listNode.next;
}
return null;
}
}
/**
* 汇编语言中有一种移位指令叫做循环左移(ROL),
* 现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,
* 请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,
* 即“XYZdefabc”。是不是很简单?OK,搞定它!
* @param str
* @param n
* @return
*/
public static String LeftRotateString(String str,int n) {
int count;
//字符串为空
if (str.length() == 0){
return "";
}
//字符串不为空并且n大于字符串长度
if (n > str.length()){
count = n%str.length(); //循环str长度倍的话,顺序不变,所以取余即可
}else {
count = n;
}
return str.substring(count) + str.substring(0, count);
}
/**
* 给定两个字符串,请编写程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
* 这里规定大小写为不同字符,且考虑字符串重点空格。
* 给定一个string stringA和一个string stringB,请返回一个bool,代表两串是否重新排列后可相同。
* 保证两串的长度都小于等于5000。
* 思路:所有字符总数为256,定义两个个256的数组,下标分别表示字符的ASCII值,对应数值表示出现次数,
* 统计AB字符串后遍历两个数组比较对应位置数值是否相同即可。
* @param stringA
* @param stringB
* @return
*/
public boolean checkSam(String stringA, String stringB) {
//两字符串存在空的情况
if (stringA == null || stringB == null){
return false;
}
/**
* 两字符串都不为空
* 长度不相等则直接返回false
*/
if (stringA.length() != stringB.length()){
return false;
}
int[] strA = new int[256];
int[] strB = new int[256];
for(int i = 0; i < stringA.length(); i++){
strA[stringA.charAt(i)]++;
strB[stringB.charAt(i)]++;
}
//遍历数组所有元素,进行对比
for (int i = 0; i < 256; i++){
if (strA[i] != strB[i]){
return false;
}
}
return true;
}
/**
* 利用字符重复出现的次数,编写一个方法,实现基本的字符串压缩功能。
* 比如,字符串“aabcccccaaa”经压缩会变成“a2b1c5a3”。若压缩后的字符串没有变短,则返回原先的字符串。
* 给定一个string iniString为待压缩的串(长度小于等于10000),保证串内字符均由大小写英文字母组成,返回一个string,为所求的压缩后或未变化的串。
* @param iniString
* @return
*/
public static String zipString(String iniString) {
StringBuffer stringBuffer = new StringBuffer();
int count = 1;
for(int i = 0; i < iniString.length()-1; i++){
if(iniString.charAt(i) == iniString.charAt(i+1)){
count++;
}else{
stringBuffer.append(iniString.charAt(i));
stringBuffer.append(count);
count = 1;
}
}
//System.out.println("stringBuffer = " + stringBuffer.toString());
stringBuffer.append(iniString.charAt(iniString.length()-1));
stringBuffer.append(count);
//System.out.println("s.length = " + stringBuffer.length() + ", s = " + stringBuffer.toString());
if(stringBuffer.length() >= iniString.length()){
return iniString;
}else{
return stringBuffer.toString();
}
}
/**
* 请编写一个算法,若N阶方阵中某个元素为0,则将其所在的行与列清零。
* 给定一个N阶方阵int[][](C++中为vector<vector><int>>)mat和矩阵的阶数n,
* 请返回完成操作后的int[][]方阵,保证n小于等于300,矩阵中的元素为int范围内。
*/
public int[][] clearZero(int[][] mat, int n) {
Set<Integer> setX = new HashSet<Integer>();
Set<Integer> setY = new HashSet<Integer>();
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(mat[i][j] == 0){
setX.add(i);
setY.add(j);
}
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(setX.contains(i) || setY.contains(j)){
mat[i][j] = 0;
}
}
}
return mat;
}
好好做题,努力搬砖,总有一天能娶得起媳妇儿,年轻人,别乱想。