面试题—小算法50题
1、递归算法判断一个数组是否是递增数组
Java实现:
package com.mian.algorithm; public class ArrayIsIncrement { public static void main(String[] args) { ArrayIsIncrement arrayIsIncrement=new ArrayIsIncrement(); int[] arr={1,2,3,4,5,6,7}; int[] ar={0,9,4,1,2,}; System.out.println(arrayIsIncrement.arrayIsIncrement(arr,arr.length)); System.out.println(arrayIsIncrement.arrayIsIncrement(ar,ar.length)); } private boolean arrayIsIncrement(int[] arr,int size){ if(size==1){ return true; } return arr[size-1]>=arr[size-2]&&arrayIsIncrement(arr,size-1); } }
C++实现:
1 bool arrayIsIncrement(vector<int> &arr, int size) 2 { 3 if (size == 1) 4 return true; 5 return arr[size - 1] >= arr[size - 2] && arrayIsIncrement(arr, size - 1); 6 }
2、二分查找的递归与非递归实现
二分查找的时间复杂度是O(logn)
(1)递归实现
Java实现:
package com.mian.algorithm; import com.sun.org.apache.bcel.internal.generic.BIPUSH; public class BinarySearchRecur { public static void main(String[] args) { int arr[]={1,2,3,5,7,9,11}; int target=7; BinarySearchRecur bs=new BinarySearchRecur(); int index=bs.binarySearchRecur(arr,0,arr.length-1,target); System.out.println(index); } private int binarySearchRecur(int[] arr,int start,int end,int target){ if(start>end){ return -1; } int mid=(start+end)>>1; if(arr[mid]==target){ return mid; }else if(arr[mid]>target){ return binarySearchRecur(arr,start,mid-1,target); }else{ return binarySearchRecur(arr,mid+1,end,target); } } }
C++实现:
1 int binarySearchRecur(vector<int> &arr, int target) 2 { 3 int size = arr.size(); 4 if (size == 0 || arr.empty()) 5 return -1; 6 return binarySearchRecursion(arr, 0, size - 1, target); 7 } 8 9 int binarySearchRecursion(vector<int> &arr, int start, int end, int target) 10 { 11 if (start > end) 12 return -1; 13 int mid = (start + end) / 2; 14 if (arr[mid] == target) 15 return mid; 16 else if (arr[mid] > target) 17 return binarySearchRecursion(arr, start, mid - 1, target); 18 else 19 return binarySearchRecursion(arr, mid + 1, end, target); 20 }
(2)非递归实现
Java实现:
package com.mian.algorithm; public class BinarySearch { public static void main(String[] args) { int arr[]={1,2,3,5,7,9,11}; int target=7; BinarySearch bs=new BinarySearch(); int index=bs.binarySearch(arr,target); System.out.println(index); } private int binarySearch(int[] arr,int target){ int size=arr.length; if(size==0||arr==null){ return -1; } int start=0; int end=size-1; int mid=0; while(start<=end){ mid=(start+end)>>1; if(arr[mid]>target){ end=mid-1; }else if(arr[mid]<target){ start=mid+1; }else{ while(mid-1>=0){ if(arr[mid-1]==target){ --mid; }else{ break; } } return mid; } } return -1; } }
C++实现:
1 int binarySearch(vector<int> &arr, int target) 2 { 3 int size = arr.size(); 4 if (size == 0 || arr.empty()) 5 return -1; 6 int start = 0; 7 int end = size - 1; 8 int mid = 0; 9 while (start <= end) 10 { 11 mid = (start + end) / 2; 12 if (arr[mid] > target) 13 end = mid - 1; 14 else if (arr[mid] < target) 15 start = mid + 1; 16 else 17 { 18 //元素重复则返回第一个元素的索引 19 while (mid - 1 >= 0) 20 if (arr[mid - 1] == target) 21 --mid; 22 else 23 break; 24 return mid; 25 } 26 } 27 return -1; 28 }
3、正整数序列Q中的每个元素都至少能被正整数a和b中的一个整除,现给定a和b,如何计算出Q中的前N项?
例如,当 a=3,b=5,N=6时,序列为3,5,6,9,10,12。
分析:可以和归并排序联系起来,给定两个数组 A、B,数组 A 存放:3 x 1,3 x 2,3 x 3,…
数组 B 存放 5 x 1,5 x 2,5 x 3,… 有两个指针 i、j,分别指向 A、B 的第一个元素,取 Min(A[ i ], B[ j ]),
并将较小值的指针前移,然后继续比较(即归并排序中的“合并两个有序序列“)。
当然,实现时没有必要申请两个数组,用两个变量即可
Java实现:
package com.mian.algorithm; public class CreateArray { public static void main(String[] args) { CreateArray createArray=new CreateArray(); int[] res=createArray.createArray(3,5,6); for(int i=0;i<res.length;++i){ System.out.print(res[i]+"\t"); } } private int[] createArray(int a,int b,int n){ int[] res=new int[n]; if(n<=0){ return null; } int i=1,j=1; int k=0; while(k<n){ if(i*a<j*b){ res[k++]=i*a; ++i; }else{ res[k++]=j*b; ++j; } } return res; } }
C++实现:
1 vector<int> createArray(int a, int b, int n) 2 { 3 vector<int> res(n); 4 if (n <= 0) 5 return res; 6 int i = 1, j = 1; 7 int k = 0; 8 while (k < n) 9 { 10 if (i*a < j*b) 11 { 12 res[k++] = i*a; 13 ++i; 14 } 15 else 16 { 17 res[k++] = j*b; 18 ++j; 19 } 20 } 21 return res; 22 }
4、删除数组中重复的元素
Java实现:
package com.mian.algorithm; import java.util.ArrayList; import java.util.List; public class DeleteRepeateEle { public static void main(String[] args) { DeleteRepeateEle dre=new DeleteRepeateEle(); int[] arr={1,3,5,2,3,5,6,2}; List<Integer> res=dre.deleteRepeateEle(arr); for(int i=0;i<res.size();++i){ System.out.print(res.get(i)+"\t"); } } private List<Integer> deleteRepeateEle(int[] arr){ List<Integer> res=new ArrayList<>(); int size=arr.length; if(size<=1||arr==null){ return res; } int min=Integer.MAX_VALUE; int max=Integer.MIN_VALUE; for(int i=0;i<size;++i){ if(arr[i]<min){ min=arr[i]; } if(arr[i]>max){ max=arr[i]; } } int[] help=new int[max-min+1]; for(int i=0;i<size;++i){ ++help[arr[i]-min]; } for(int i=0;i<size;++i){ if(help[arr[i]-min]==1){ res.add(arr[i]); } } return res; } }
C++实现:
1 vector<int> deleteRepeateEle(vector<int> &arr) 2 { 3 vector<int> res; 4 int size = arr.size(); 5 if (size <= 1 || arr.empty()) 6 return res; 7 int min = INT_MAX; 8 int max = INT_MIN; 9 for (int i = 0; i < size; ++i) 10 { 11 if (arr[i] < min) 12 min = arr[i]; 13 if (arr[i] > max) 14 max = arr[i]; 15 } 16 vector<int> help(max - min + 1); 17 for (int i = 0; i < size; ++i) 18 ++help[arr[i] - min]; 19 for (int i = 0; i < size; ++i) 20 if (help[arr[i] - min] == 1) 21 res.push_back(arr[i]); 22 return res; 23 }
5、删除单链表中重复的结点
(1)递归实现,保留一个重复的结点元素
Java实现:
package com.mian.algorithm; import java.util.Scanner; public class DeleteRepeateNodeRecur { public static void main(String[] args) { DeleteRepeateNodeRecur drnr=new DeleteRepeateNodeRecur(); ListNode head=drnr.createList(); drnr.printListNode(head); ListNode singleHead=drnr.deleteRepeateNodeRecur(head); drnr.printListNode(singleHead); } private ListNode deleteRepeateNodeRecur(ListNode head){ if(head==null||(head!=null&&head.next==null)){ return head; } ListNode tmp=head; ListNode next=deleteRepeateNodeRecur(head.next); if(next!=null){ if(tmp.val==next.val){ tmp.next=next.next; } } return head; } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter list val (enter 100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printListNode(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode { 6 public: 7 int val; 8 ListNode* next; 9 ListNode(){} 10 ListNode(int x):val(x),next(nullptr){} 11 }; 12 13 void printListNode(ListNode* head) 14 { 15 ListNode* cur = head; 16 while (cur) 17 { 18 cout << cur->val << " "; 19 cur = cur->next; 20 } 21 cout << endl; 22 } 23 24 ListNode* createListNode() 25 { 26 int in; 27 ListNode* head = nullptr; 28 cout << "enter list val (enter 100 to quit):"; 29 cin >> in; 30 if (in == 100) 31 return head; 32 else 33 { 34 head = new ListNode(in); 35 head->next = createListNode(); 36 } 37 return head; 38 } 39 40 ListNode* deleteRepeateNode(ListNode* head) 41 { 42 if (head == nullptr) 43 return nullptr; 44 if (head != nullptr&&head->next == nullptr) 45 return head; 46 ListNode* tmp = head; 47 ListNode* next = deleteRepeateNode(head->next); 48 if (next) 49 if (tmp->val == next->val) 50 tmp->next = next->next; 51 return head; 52 } 53 54 int main() 55 { 56 ListNode* head = createListNode(); 57 printListNode(head); 58 printListNode(deleteRepeateNode(head)); 59 60 return 0; 61 }
(2)非递归实现,保留一个重复的结点元素
Java实现:
package com.mian.algorithm; import java.util.Scanner; public class DeleteRepeateNode { public static void main(String[] args) { DeleteRepeateNode drnr=new DeleteRepeateNode(); ListNode head=drnr.createList(); drnr.printListNode(head); ListNode singleHead=drnr.deleteRepeateNode(head); drnr.printListNode(singleHead); } private ListNode deleteRepeateNode(ListNode head){ if(head==null||(head!=null&&head.next==null)){ return head; } ListNode cur=head; while(cur!=null){ while(cur.next!=null&&cur.val==cur.next.val){ cur.next=cur.next.next; } cur=cur.next; } return head; } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter list val (enter 100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printListNode(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode { 6 public: 7 int val; 8 ListNode* next; 9 ListNode() {} 10 ListNode(int x) :val(x), next(nullptr) {} 11 }; 12 13 void printListNode(ListNode* head) 14 { 15 ListNode* cur = head; 16 while (cur) 17 { 18 cout << cur->val << " "; 19 cur = cur->next; 20 } 21 cout << endl; 22 } 23 24 ListNode* createListNode() 25 { 26 int in; 27 ListNode* head = nullptr; 28 cout << "enter list val (enter 100 to quit):"; 29 cin >> in; 30 if (in == 100) 31 return head; 32 else 33 { 34 head = new ListNode(in); 35 head->next = createListNode(); 36 } 37 return head; 38 } 39 40 ListNode* deleteRepeateNode(ListNode* head) 41 { 42 ListNode* cur = head; 43 while (cur) 44 { 45 while (cur->next&&cur->val == cur->next->val) 46 cur->next = cur->next->next; 47 cur = cur->next; 48 } 49 return head; 50 } 51 52 int main() 53 { 54 ListNode* head = createListNode(); 55 printListNode(head); 56 printListNode(deleteRepeateNode(head)); 57 58 return 0; 59 }
(3)递归实现,不保留重复结点元素
Java实现:
package com.mian.algorithm; import java.util.Scanner; public class DeleteRepeateRecur { public static void main(String[] args) { DeleteRepeateRecur dr=new DeleteRepeateRecur(); ListNode head=dr.createList(); dr.printListNode(head); ListNode singleHead=dr.deleteRepeateRecur(head); dr.printListNode(singleHead); } private ListNode deleteRepeateRecur(ListNode head){ if(head==null||(head!=null&&head.next==null)){ return head; } ListNode cur=null; if(head.val==head.next.val){ cur=head.next; while(cur!=null&&cur.val==head.val){ cur=cur.next; } return deleteRepeateRecur(cur); }else{ cur=head.next; head.next=deleteRepeateRecur(cur); return head; } } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter list val (enter 100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printListNode(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode { 6 public: 7 int val; 8 ListNode* next; 9 ListNode() {} 10 ListNode(int x) :val(x), next(nullptr) {} 11 }; 12 13 void printListNode(ListNode* head) 14 { 15 ListNode* cur = head; 16 while (cur) 17 { 18 cout << cur->val << " "; 19 cur = cur->next; 20 } 21 cout << endl; 22 } 23 24 ListNode* createListNode() 25 { 26 int in; 27 ListNode* head = nullptr; 28 cout << "enter list val (enter 100 to quit):"; 29 cin >> in; 30 if (in == 100) 31 return head; 32 else 33 { 34 head = new ListNode(in); 35 head->next = createListNode(); 36 } 37 return head; 38 } 39 40 ListNode* deleteRepeateNode(ListNode* head) 41 { 42 if (!head || head && !head->next) 43 return head; 44 ListNode* cur = nullptr; 45 if (head->val == head->next->val) 46 { 47 cur = head->next; 48 while (cur&&cur->val == head->val) 49 cur = cur->next; 50 return deleteRepeateNode(cur); 51 } 52 else 53 { 54 cur = head->next; 55 head->next = deleteRepeateNode(cur); 56 return head; 57 } 58 } 59 60 int main() 61 { 62 ListNode* head = createListNode(); 63 printListNode(head); 64 printListNode(deleteRepeateNode(head)); 65 66 return 0; 67 }
(4)非递归实现,不保留重复结点元素
Java实现:
package com.mian.algorithm; import java.util.Scanner; public class DeleteRepeate{ public static void main(String[] args) { DeleteRepeate dr=new DeleteRepeate(); ListNode head=dr.createList(); dr.printListNode(head); ListNode singleHead=dr.deleteRepeate(head); dr.printListNode(singleHead); } private ListNode deleteRepeate(ListNode head){ if(head==null||(head!=null&&head.next==null)){ return head; } ListNode first=new ListNode(-1); first.next=head; ListNode p=head; ListNode last=first; while (p!=null&&p.next!=null){ if(p.val==p.next.val){ int val=p.val; while(p!=null&&p.val==val){ p=p.next; } last.next=p; }else { last=p; p=p.next; } } return first.next; } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter list val (enter 100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printListNode(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode { 6 public: 7 int val; 8 ListNode* next; 9 ListNode() {} 10 ListNode(int x) :val(x), next(nullptr) {} 11 }; 12 13 void printListNode(ListNode* head) 14 { 15 ListNode* cur = head; 16 while (cur) 17 { 18 cout << cur->val << " "; 19 cur = cur->next; 20 } 21 cout << endl; 22 } 23 24 ListNode* createListNode() 25 { 26 int in; 27 ListNode* head = nullptr; 28 cout << "enter list val (enter 100 to quit):"; 29 cin >> in; 30 if (in == 100) 31 return head; 32 else 33 { 34 head = new ListNode(in); 35 head->next = createListNode(); 36 } 37 return head; 38 } 39 40 ListNode* deleteRepeateNode(ListNode* head) 41 { 42 ListNode* first = new ListNode(-1); 43 first->next = head; 44 ListNode* p = head; 45 ListNode* last = first; 46 while (p&&p->next) 47 { 48 if (p->val == p->next->val) 49 { 50 int val = p->val; 51 while (p&&p->val == val) 52 p = p->next; 53 last->next = p; 54 } 55 else 56 { 57 last = p; 58 p = p->next; 59 } 60 } 61 return first->next; 62 } 63 64 int main() 65 { 66 ListNode* head = createListNode(); 67 printListNode(head); 68 printListNode(deleteRepeateNode(head)); 69 70 return 0; 71 }
6、浮点数的平方根
(1)暴力搜索
Java实现:
package com.mian.algorithm; public class MySqrt{ public static void main(String[] args) { MySqrt mySqrt=new MySqrt(); int s=mySqrt.mySqrt(9); System.out.println(s); } private int mySqrt(int x){ if(x<=0){ return x; } int begin=1; int end=x; int mid=0; while(begin<=end){ mid=(begin+end)>>1; if(mid==x/mid){ return mid; }else if(mid<x/mid){ begin=mid+1; }else{ end=mid-1; } } return end;//结束条件end一定<begin,所以返回end } }
C++实现:
1 int mySqrt(int x) 2 { 3 if(x<=0) 4 return x; 5 int begin=1; 6 int end=x; 7 int mid=0; 8 while(begin<=end) 9 { 10 mid=(begin+end)/2; 11 if(mid==x/mid) 12 return mid; 13 else if(mid<x/mid) 14 begin=mid+1; 15 else 16 end=mid-1; 17 } 18 return end;//结束条件end一定<begin,所以返回end 19 }
(2)牛顿迭代法
Java实现:
package com.mian.algorithm; public class MySqrt{ public static void main(String[] args) { MySqrt mySqrt=new MySqrt(); int s=mySqrt.mySqrt(9); System.out.println(s); } private int mySqrt(int x){ long v=x; while(v*v>x){ v=(v+x/v)>>1; } return (int)v; } }
C++实现:
1 int mySqrt(int x) 2 { 3 long long v=x; 4 while(v*v>x) 5 v=(v+x/v)>>1; 6 return v; 7 }
7、交换单链表中任意两个结点
Java实现:
package com.mian.algorithm; import java.util.List; import java.util.Scanner; public class ExchangeTwoNode { public static void main(String[] args) { ExchangeTwoNode et=new ExchangeTwoNode(); ListNode head=et.createList(); et.printList(head); ListNode node1=head.next.next; ListNode node2=head.next.next.next.next.next; ListNode node=et.exchangeTwoNode(head,node1,node2); et.printList(node); } private ListNode exchangeTwoNode(ListNode head,ListNode node1,ListNode node2){ if(head==null||node1==null||node2==null){ return head; } if(node1.val==node2.val){ return head; } if(node1.next==node2){ ListNode pre=findPreNode(head,node1); pre.next=node2; node1.next=node2.next; node2.next=node1; }else if(node2.next==node1){ ListNode pre=findPreNode(head,node2); pre.next=node1; node2.next=node1.next; node1.next=node2; }else if(node1!=node2){ ListNode pre1=findPreNode(head,node1); ListNode pre2=findPreNode(head,node2); ListNode tmp=node1.next; node1.next=node2.next; node2.next=tmp; pre1.next=node2; pre2.next=node1; } return head; } ListNode createList(){ int val; ListNode head=null; System.out.println("enter list value (enter 100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } ListNode findPreNode(ListNode head,ListNode node){ if(head==null||node==null){ return null; } ListNode p=head; while(p!=null){ if(p.next==node){ return p; }else{ p=p.next; } } return null; } private void printList(ListNode head){ ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode { 6 public: 7 int val; 8 ListNode* next; 9 ListNode() {} 10 ListNode(int x) :val(x), next(nullptr) {} 11 }; 12 13 void printListNode(ListNode* head) 14 { 15 ListNode* cur = head; 16 while (cur) 17 { 18 cout << cur->val << " "; 19 cur = cur->next; 20 } 21 cout << endl; 22 } 23 24 ListNode* findPreNode(ListNode* head, ListNode* node) 25 { 26 if (head == nullptr || node == nullptr) 27 return nullptr; 28 ListNode* p = head; 29 while (p) 30 if (p->next == node) 31 return p; 32 else 33 p = p->next; 34 return nullptr; 35 } 36 37 ListNode* exchangeTwoNode(ListNode* head, ListNode* node1, ListNode* node2) 38 { 39 if (head == nullptr || node1 == nullptr || node2 == nullptr) 40 return head; 41 if (node1->val == node2->val) 42 return head; 43 if (node1->next == node2) 44 { 45 ListNode* pre = findPreNode(head, node1); 46 pre->next = node2; 47 node1->next = node2->next; 48 node2->next = node1; 49 } 50 else if (node2->next == node1) 51 { 52 ListNode* pre = findPreNode(head, node2); 53 pre->next = node1; 54 node2->next = node1->next; 55 node1->next = node2; 56 } 57 else if (node1 != node2) 58 { 59 ListNode* pre1 = findPreNode(head, node1); 60 ListNode* pre2 = findPreNode(head, node2); 61 ListNode* tmp = node1->next; 62 node1->next = node2->next; 63 node2->next = tmp; 64 pre1->next = node2; 65 pre2->next = node1; 66 } 67 return head; 68 } 69 70 ListNode* createNode() 71 { 72 int in; 73 ListNode* head = nullptr; 74 cout << "enter list value (enter 100 to quit):"; 75 cin >> in; 76 if (in == 100) 77 return head; 78 else 79 { 80 head = new ListNode(in); 81 head->next = createNode(); 82 } 83 return head; 84 } 85 86 int main() 87 { 88 ListNode* head = createNode(); 89 ListNode* node1 = head->next; 90 ListNode* node2 = head->next->next->next->next; 91 printListNode(head); 92 printListNode(exchangeTwoNode(head, node1, node2)); 93 94 return 0; 95 }
8、如何判断一个整数 x 是否可以表示成 n(n >= 2)个连续正整数的和。
分析:假设 x 可以表示成 n(n >= 2)个连续正整数的和,那么x = m + (m + 1) + (m + 2) + … + (m + n - 1),其中 m 为分解成的连续整数中最小的那一个(且 m 是大于等于 1 的正整数),可推出 x = (2m + n - 1)*n/2,变换之后 m = (2*x/n - n + 1)/2;由 m 的取值范围可知 (2*x/n - n + 1)/2 >= 1,又因为 m 是正整数,所以(2*x/n - n + 1) 一定要为偶数;否则m = (2*x/n - n + 1)/2 就是小数,不符合要求;(注意:(2*x/n - n + 1) 看成是 float 类型的)。给定一个 n,看 x 是否能分解成 n 个连续整数的和,可以判断是否存在 m,也就是 (2*x/n - n + 1) 是否是偶数的问题。
Java实现:
package com.mian.algorithm; public class ContinuousSequence { public static void main(String[] args) { findContinuousSequence(32,5); } private static void findContinuousSequence(int x,int n){ float tmp=(float)2*x/n-(float)(n-1); int m=(int)tmp/2; if((int)tmp%2==0&&m>=1){ System.out.print("x可分解为: "); int start=m; int end=m+n-1; while(start<=end){ System.out.print(start+"\t"); ++start; } System.out.println(); }else{ System.out.println("x不可分解"); } } }
C++实现:
1 void findContinuousSequence(int x, int n) 2 { 3 float temp = (float)2 * x / n - (float)(n - 1); 4 int m = (int)temp / 2; 5 if ((int)temp % 2 == 0 && m >= 1) 6 { 7 cout << "x可分解为 : "; 8 int start = m; 9 int end = m + n - 1; 10 while (start <= end) 11 { 12 cout << start << " "; 13 start++; 14 } 15 cout << endl; 16 } 17 else 18 cout << "x不可分解" << endl; 19 }
9、给一个由n-1个数组成的未经排序的数列,其元素都是1—n中的不同的整数。找出缺失的整数?
Java实现:
package com.mian.algorithm; import java.io.FileOutputStream; public class FindLost { public static void main(String[] args) { FindLost findLost=new FindLost(); int arr[]={1,2,3,5,9,7,8,6}; findLost.findLost(arr); } private void findLost(int[] arr){ int size=arr.length; if(size==0||arr==null){ return; } int sum1=0; int sum2=0; for(int i=0;i<size;++i){ sum1+=arr[i]; sum2+=i; } sum2+=size; System.out.println((sum2-sum1+size+1)); } }
C++实现:
1 void findLost(vector<int> &arr) 2 { 3 int size = arr.size(); 4 if (arr.empty() || size == 0) 5 return; 6 int sum1 = 0; 7 int sum2 = 0; 8 for (int i = 0; i < size; ++i) 9 { 10 sum1 += arr[i]; 11 sum2 += i; 12 } 13 sum2 += size; 14 cout << (sum2 - sum1 + size + 1) << endl; 15 }
10、字符串中第一个出现一次的字符
Java实现:
package com.mian.algorithm; import java.util.HashMap; import java.util.Map; public class FindFirstCharWithMap { public static void main(String[] args) { FindFirstCharWithMap fcm=new FindFirstCharWithMap(); fcm.findFirstCharWithMap("afdazfexafd"); fcm.findFirstChar("afdazfexafd"); } private void findFirstChar(String str){ int size=str.length(); if(size==0||str.isEmpty()){ return; } int[] hash=new int[256]; for(int i=0;i<size;++i){ ++hash[str.charAt(i)]; } for(int i=0;i<size;++i){ if(hash[str.charAt(i)]==1){ System.out.println(str.charAt(i)); break; } } } private void findFirstCharWithMap(String str){ int size=str.length(); if(size==0||str.isEmpty()){ return; } Map<Character,Integer> map=new HashMap<>(); for(int i=0;i<size;++i){ if(map.containsKey(str.charAt(i))){ map.put(str.charAt(i),map.get(str.charAt(i))+1); }else{ map.put(str.charAt(i),1); } } for(int i=0;i<size;++i){ if(map.get(str.charAt(i))==1){ System.out.println(str.charAt(i)); break; } } } }
C++实现:
(1)unordered_map
1 void findFirstCharWithMap(string str) 2 { 3 int size = str.size(); 4 if (size == 0 || str.empty()) 5 return; 6 unordered_map<char, int> m; 7 for (int i = 0; i < size; ++i) 8 ++m[str[i]]; 9 for (int i = 0; i < size; ++i) 10 if (m[str[i]] == 1) 11 { 12 cout << str[i] << endl; 13 break; 14 } 15 }
(2)vector
1 void findFirstChar(string str) 2 { 3 int size = str.size(); 4 if (size == 0 || str.empty()) 5 return; 6 vector<int> hash(256,0); 7 for (int i = 0; i < size; ++i) 8 ++hash[str[i]]; 9 for (int i = 0; i < size; ++i) 10 if (hash[str[i]] == 1) 11 { 12 cout << str[i] << endl; 13 break; 14 } 15 }
11、求两个数组的交集
Java实现:
package com.mian.demo; import java.util.Arrays; public class IntersectArray { public static void main(String[] args) { IntersectArray intersectArray=new IntersectArray(); int[] arr1={9,4,3,0,2,7,6,8}; int[] arr2={5,2,8,1,0,3}; intersectArray.intersectArray(arr1,arr2); } private void intersectArray(int[] arr1,int[] arr2){ int size1=arr1.length; int size2=arr2.length; if(arr1==null||size1==0||arr2==null||size2==0){ return; } Arrays.sort(arr1); Arrays.sort(arr2); int i=0,j=0; while(i<size1&&j<size2){ if(arr1[i]==arr2[j]){ System.out.print(arr1[i]+"\t"); ++i; ++j; }else if(arr1[i]>arr2[j]){ ++j; }else{ ++i; } } System.out.println(); } }
C++实现:
1 void intersectArray(vector<int> &arr1, vector<int> &arr2) 2 { 3 int size1 = arr1.size(); 4 int size2 = arr2.size(); 5 if (arr1.empty() || arr2.empty() || size1 == 0 || size2 == 0) 6 return; 7 sort(arr1.begin(), arr1.end()); 8 sort(arr2.begin(),arr2.end()); 9 int i = 0, j = 0; 10 while (i < size1 && j < size2) { 11 if (arr1[i] == arr2[j]) { 12 cout << arr1[i] << " "; 13 ++i; 14 ++j; 15 } 16 else if (arr1[i] > arr2[j]) { 17 ++j; 18 } 19 else { 20 ++i; 21 } 22 } 23 cout << endl; 24 }
12、如何判断一个数组中的数值是否连续相邻
一个整数数组,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现;0是例外,可以反复出现。
设计一个算法,判断这个数组中的元素是否连续相邻。
需要注意以下4点:
(1)数值允许是乱序的,如 8 7 5 0 6。
(2)0可以通配任意数值,如8 7 5 0 6中的0可以通配成9或者4.
(3)0可以多次出现。
(4)全0算连续,只有一个非0算连续。
分析:如果没有0的存在,要组成连续的数列,最大值和最小值的差距必须是n-1;存在0的情况下,只要最大值可最小值的差距小于n-1就可以了,缺失的数值可以用0通配。所以找出数列中非0的最大值和非0的最小值,时间复杂度为O(n)。如果非0最大-非0最小+1<n,即非0最大-非0最小<=n-1,则这n个数值连续相邻。否则,不连续相邻。因此,总体复杂度为O(n)。
Java实现:
package com.mian.demo; public class IsContinues { public static void main(String[] args) { } private boolean isContinues(int[] arr){ int size=arr.length; if(arr==null||size==0){ return true; } int max=Integer.MIN_VALUE; int min=Integer.MAX_VALUE; for(int i=0;i<size;++i){ if(arr[i]!=0){ if(arr[i]>max){ max=arr[i]; } if(arr[i]<min){ min=arr[i]; } } } return (max-min)<=(size-1)?true:false; } }
C++实现:
1 bool isContinues(vector<int> &arr) 2 { 3 int size = arr.size(); 4 if (arr.empty() || size == 0) 5 return true; 6 int max = arr[0]; 7 int min = arr[0]; 8 for (int i = 0; i < size; ++i) 9 { 10 if (arr[i] != 0) 11 { 12 if (arr[i] > max) 13 max = arr[i]; 14 if (arr[i] < min) 15 min = arr[i]; 16 } 17 } 18 return (max - min) <= (size - 1) ? true : false; 19 }
13、删除单链表的节点
(1)删除的结点以值的形式给出,链表中结点的值不重复
Java实现:
package com.mian.demo; import java.util.List; import java.util.Scanner; public class DeleteListNode { public static void main(String[] args) { DeleteListNode deleteListNode=new DeleteListNode(); ListNode head=deleteListNode.createList(); deleteListNode.printList(head); deleteListNode.deleteListNode(head,7); deleteListNode.printList(head); } private void deleteListNode(ListNode head,int val){ if(head==null){ return; } ListNode p=head; ListNode last=head; if(head.val==val){ head.val=head.next.val; head.next=head.next.next; }else{ while(last.next!=null){ last=last.next; } if(last.val!=val){ while(p.next!=null){ if(p.next.val==val){ p.next=p.next.next; } p=p.next; } }else{ while(p.next.next!=null){ p=p.next; } p.next=null; } } } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter list val (enter 100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode 6 { 7 public: 8 int val; 9 ListNode* next; 10 ListNode(){} 11 ListNode(int x):val(x),next(nullptr){} 12 }; 13 14 ListNode* createList() 15 { 16 int in; 17 ListNode* head = nullptr; 18 cout << "enter list val (enter 100 to quit):"; 19 cin >> in; 20 if (in == 100) 21 return head; 22 else 23 { 24 head = new ListNode(in); 25 head->next = createList(); 26 } 27 return head; 28 } 29 30 void printNode(ListNode* head) 31 { 32 ListNode* p = head; 33 while (p) 34 { 35 cout << p->val << " "; 36 p = p->next; 37 } 38 cout << endl; 39 } 40 41 void deleteListNode(ListNode* head, int val) 42 { 43 if (head == nullptr) 44 return; 45 ListNode* p = head; 46 ListNode* last = head; 47 if (head->val == val) 48 { 49 head->val = head->next->val; 50 head->next = head->next->next; 51 } 52 else 53 { 54 while (last->next) 55 last = last->next; 56 if (last->val != val) 57 { 58 while (p->next) 59 { 60 if (p->next->val == val) 61 p->next = p->next->next; 62 p = p->next; 63 } 64 } 65 else 66 { 67 while (p->next->next) 68 p = p->next; 69 p->next = nullptr; 70 } 71 } 72 } 73 74 75 int main() 76 { 77 ListNode* head=createList(); 78 printNode(head); 79 deleteListNode(head, 3); 80 printNode(head); 81 82 return 0; 83 }
(2)删除的结点以节点的形式给出
Java实现:
package com.mian.demo; import java.util.Scanner; public class DeleteNode { public static void main(String[] args){ DeleteNode deleteNode=new DeleteNode(); ListNode head=deleteNode.createList(); deleteNode.printList(head); //删除头结点 ListNode del=head; deleteNode.deleteListNode(head,del); deleteNode.printList(head); //删除尾结点 ListNode last=head; while(last.next!=null){ last=last.next; } deleteNode.deleteListNode(head,last); deleteNode.printList(head); //删除中间结点 ListNode mid=head.next.next.next; deleteNode.deleteListNode(head,mid); deleteNode.printList(head); } private void deleteListNode(ListNode head,ListNode node){ if(head==null||node==null){ return; } if(head==node){ head.val=head.next.val; head.next=head.next.next; }else if(node.next!=null){ ListNode p=node.next; node.val=p.val; node.next=p.next; }else{ ListNode p=head; while(p!=null){ if(p.next==node){ p.next=null; } p=p.next; } } } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter list val (enter 100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 #include<iostream> 2 #include<unordered_map> 3 4 using namespace std; 5 6 class ListNode 7 { 8 public: 9 int val; 10 ListNode* next; 11 ListNode(){} 12 ListNode(int x):val(x),next(nullptr){} 13 }; 14 15 ListNode* createNode() 16 { 17 int in; 18 ListNode* head = nullptr; 19 cout << "enter list value (enter 100 to quit):"; 20 cin >> in; 21 if (in == 100) 22 return head; 23 else 24 { 25 head = new ListNode(in); 26 head->next = createNode(); 27 } 28 return head; 29 } 30 31 void printList(ListNode* head) 32 { 33 if (head == nullptr) 34 return; 35 ListNode* p = head; 36 while (p) 37 { 38 cout << p->val << " "; 39 p = p->next; 40 } 41 cout << endl; 42 } 43 44 void deleteListNode(ListNode* head,ListNode* node) 45 { 46 if (head == nullptr || node == nullptr) 47 return; 48 if (head == node) 49 { 50 head->val = head->next->val; 51 head->next = head->next->next; 52 } 53 else if (node->next) 54 { 55 ListNode* p = node->next; 56 node->val = p->val; 57 node->next = p->next; 58 } 59 else 60 { 61 ListNode* p = head; 62 while (p) 63 { 64 if (p->next == node) 65 p->next = nullptr; 66 p = p->next; 67 } 68 } 69 } 70 71 int main() 72 { 73 ListNode* head = createNode(); 74 printList(head); 75 //删除头结点 76 ListNode* del = head; 77 deleteListNode(head, del); 78 printList(head); 79 //删除尾结点 80 ListNode* last = head; 81 while (last->next) 82 last = last->next; 83 deleteListNode(head, last); 84 printList(head); 85 //删除中间结点 86 ListNode* mid = head->next->next->next; 87 deleteListNode(head, mid); 88 printList(head); 89 90 return 0; 91 }
14、单链表中插入节点
分三种情况:插入到链表首部、中间、尾部
Java实现:
package com.mian.demo; import java.util.List; import java.util.Scanner; public class InsertNode { public static void main(String[] args){ InsertNode insertNode=new InsertNode(); ListNode head=insertNode.createList(); insertNode.printList(head); insertNode.insertNode(head,3,5); insertNode.printList(head); } private void insertNode(ListNode head,int val,int pos){ ListNode node=new ListNode(val); ListNode p=head; ListNode last=head; if(pos==0){ node.val=head.val; head.val=val; node.next=head.next; head.next=node; }else{ int index=1; while(p!=null&&index<pos){ ++index; p=p.next; } if(p!=null){ node.next=p.next; p.next=node; }else{ while(last.next!=null){ last=last.next; } last.next=node; } } } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter list val (enter 100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode 6 { 7 public: 8 int val; 9 ListNode* next; 10 ListNode(){} 11 ListNode(int x):val(x),next(nullptr){} 12 }; 13 14 ListNode* createList() 15 { 16 int in; 17 ListNode* head = nullptr; 18 cout << "enter list val (enter 100 to quit):"; 19 cin >> in; 20 if (in == 100) 21 return head; 22 else 23 { 24 head = new ListNode(in); 25 head->next = createList(); 26 } 27 return head; 28 } 29 30 void printNode(ListNode* head) 31 { 32 ListNode* p = head; 33 while (p) 34 { 35 cout << p->val << " "; 36 p = p->next; 37 } 38 cout << endl; 39 } 40 41 void insertNode(ListNode *head, int val, int pos) 42 { 43 ListNode* node= new ListNode(val); 44 ListNode* p = head; 45 ListNode* last = head; 46 if (pos == 0) 47 { 48 node->val = head->val; 49 head->val = val; 50 node->next = head->next; 51 head->next = node; 52 } 53 else 54 { 55 int index = 1; 56 while (p&&index < pos) 57 { 58 ++index; 59 p = p->next; 60 } 61 if (p) 62 { 63 node->next = p->next; 64 p->next = node; 65 } 66 else 67 { 68 while (last->next) 69 last = last->next; 70 last->next = node; 71 } 72 } 73 } 74 75 76 int main() 77 { 78 ListNode* head=createList(); 79 printNode(head); 80 insertNode(head, 3, 5); 81 printNode(head); 82 83 return 0; 84 }
15、判断两个链表是否交叉
单链表相交是指两个链表存在完全相同的部分(不是相交与一个结点)
判断单链表相交有两种方法:
方法一:将两个链表的首尾相连,监测是否有环
Java实现:
package com.mian.demo; import java.util.Scanner; public class GetLoopNode { public static void main(String[] args) { GetLoopNode gn=new GetLoopNode(); ListNode head=gn.createList(); ListNode mid=head.next.next.next; ListNode node=gn.createList(); gn.printList(node); ListNode last=node; while(last.next!=null){ last=last.next; } last.next=mid; gn.printList(head); gn.printList(node); ListNode loopNode=gn.getLoop(head,node); System.out.println(loopNode.val); } private ListNode getLoop(ListNode f,ListNode s){ if(f==null||s==null){ return null; } ListNode last=f; while(last.next!=null){ last=last.next; } last.next=s; return getLoopNode(f); } private ListNode getLoopNode(ListNode head){ if(head==null||head.next==null){ return head; } ListNode slow=head; ListNode fast=head; while(fast!=null&&fast.next!=null){ slow=slow.next; fast=fast.next.next; if(slow==fast){ fast=head; while(slow!=fast){ slow=slow.next; fast=fast.next; } return slow; } } return null; } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter node value (100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 ListNode *getLoopNode(ListNode *head) 2 { 3 if (head == nullptr || head->next == nullptr || head->next->next == nullptr) 4 return head; 5 ListNode *n1 = head->next; 6 ListNode *n2 = head->next->next; 7 while (n1 != n2) 8 { 9 if (n1->next == nullptr || n2->next->next == nullptr) 10 return nullptr; 11 n1 = n1->next; 12 n2 = n2->next->next; 13 } 14 n2 = head; 15 while (n1 != n2) 16 { 17 n1 = n1->next; 18 n2 = n2->next; 19 } 20 return n1; 21 } 22 ListNode *getLoop(ListNode *f, ListNode *s) 23 { 24 if (f == nullptr || s == nullptr) 25 return nullptr; 26 while (s->next) 27 s = s->next; 28 s->next = f; 29 return getLoopNode(s); 30 }
方法二:如两个单链表相交,那么从相交结点开始到链表结束都是相同的结点,必然是Y字形,判断两个链表的最后一个结点是否相同即可。
Java实现:
package com.mian.demo; import java.util.Scanner; public class GetNodeWithLoop { public static void main(String[] args) { GetNodeWithLoop gn=new GetNodeWithLoop(); ListNode head=gn.createList(); ListNode mid=head.next.next.next; ListNode node=gn.createList(); gn.printList(node); ListNode last=node; while(last.next!=null){ last=last.next; } last.next=mid; gn.printList(head); gn.printList(node); ListNode loopNode=gn.getLoop(head,node); System.out.println(loopNode.val); } private ListNode getLoop(ListNode f,ListNode s){ if(f==null||s==null){ return null; } int n=0; ListNode cur1=f; ListNode cur2=s; while(cur1.next!=null){ cur1=cur1.next; ++n; } while(cur2.next!=null){ cur2=cur2.next; --n; } if(cur1!=cur2){ return null; } cur1=n>0?f:s; cur2=cur1==f?s:f; n=Math.abs(n); while(n!=0){ --n; cur1=cur1.next; } while(cur1!=cur2){ cur1=cur1.next; cur2=cur2.next; } return cur1; } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter node value (100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 ListNode *getNode(ListNode *f, ListNode *s) 2 { 3 if (f == nullptr || s == nullptr) 4 return nullptr; 5 int n = 0; 6 ListNode *cur1 = f; 7 ListNode *cur2 = s; 8 while (cur1->next) 9 { 10 cur1 = cur1->next; 11 n++; 12 } 13 while (cur2->next) 14 { 15 cur2 = cur2->next; 16 n--; 17 } 18 if (cur1 != cur2) 19 return nullptr; 20 cur1 = n > 0 ? f : s; 21 cur2 = cur1 == f ? s : f; 22 n = abs(n); 23 while (n) 24 { 25 n--; 26 cur1 = cur1->next; 27 } 28 while (cur1 != cur2) 29 { 30 cur1 = cur1->next; 31 cur2 = cur2->next; 32 } 33 return cur1; 34 }
16、找出数组中重复数字最多的数
Java实现:
package com.mian.demo; public class MaxCount { public static void main(String[] args) { MaxCount maxCount=new MaxCount(); int[] arr={9,3,5,2,1,6,3,1,2,4,5,3}; int res=maxCount.maxCount(arr); System.out.println(res); } private int maxCount(int[] arr){ int size=arr.length; int max=Integer.MIN_VALUE; int min=Integer.MAX_VALUE; for(int i=0;i<size;++i){ if(max<arr[i]){ max=arr[i]; } if(min>arr[i]){ min=arr[i]; } } int[] help=new int[max-min+1]; for(int i=0;i<size;++i){ ++help[arr[i]-min]; } int cnt=0; int res=0; for(int i=0;i<size;++i){ if(help[arr[i]-min]>cnt){ cnt=help[arr[i]-min]; res=arr[i]; } } return res; } }
C++实现:
1 int maxCount(vector<int> &arr) 2 { 3 int size = arr.size(); 4 int max = INT_MIN; 5 int min = INT_MAX; 6 for (int i = 0; i < size; ++i) 7 { 8 if (max < arr[i]) 9 max = arr[i]; 10 if (min > arr[i]) 11 min = arr[i]; 12 } 13 vector<int> help(max - min + 1); 14 15 for (int i = 0; i < size; ++i) 16 ++help[arr[i]-min]; 17 int cnt = 0; 18 int res = 0; 19 for (int i = 0; i < size; ++i) 20 if (help[arr[i] - min] > cnt) 21 { 22 cnt = help[arr[i] - min]; 23 res = arr[i]; 24 } 25 return res; 26 }
17、合并两个升序链表
(1)非递归
Java实现:
package com.mian.demo; import java.util.Scanner; public class MergeTwoList{ public static void main(String[] args) { MergeTwoList mt=new MergeTwoList(); ListNode list1=mt.createList(); ListNode list2=mt.createList(); mt.printList(list1); mt.printList(list2); ListNode node=mt.mergeList(list1,list2); mt.printList(node); } private ListNode mergeList(ListNode list1,ListNode list2){ if(list1==null&&list2==null){ return null; } if(list1==null){ return list2; } if(list2==null){ return list1; } ListNode first=new ListNode(-1); ListNode cur=first; while(list1!=null&&list2!=null){ if(list1.val<list2.val){ cur.next=list1; list1=list1.next; }else{ cur.next=list2; list2=list2.next; } cur=cur.next; } cur.next=list1!=null?list1:list2; return first.next; } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter node value (100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode 6 { 7 public: 8 int val; 9 ListNode* next; 10 ListNode() {} 11 ListNode(int x) :val(x), next(nullptr) {} 12 }; 13 14 ListNode* createList() 15 { 16 int in; 17 cout << "enter list value (enter 100 to quit):"; 18 cin >> in; 19 ListNode* head = nullptr; 20 if (in == 100) 21 return head; 22 else 23 { 24 head = new ListNode(in); 25 head->next = createList(); 26 } 27 return head; 28 } 29 30 void printList(ListNode* head) 31 { 32 if (head == nullptr) 33 return; 34 ListNode* p = head; 35 while (p) 36 { 37 cout << p->val << " "; 38 p = p->next; 39 } 40 cout << endl; 41 } 42 43 ListNode* mergeList(ListNode* list1, ListNode* list2) 44 { 45 if (!list1 && !list2) 46 return nullptr; 47 if (!list1) 48 return list2; 49 if (!list2) 50 return list1; 51 ListNode* first = new ListNode(-1); 52 ListNode* cur = first; 53 while (list1&&list2) 54 { 55 if (list1->val < list2->val) 56 { 57 cur->next = list1; 58 list1 = list1->next; 59 } 60 else 61 { 62 cur->next = list2; 63 list2 = list2->next; 64 } 65 cur = cur->next; 66 } 67 cur->next = list1 ? list1 : list2; 68 return first->next; 69 } 70 71 int main() 72 { 73 ListNode* node1 = createList(); 74 printList(node1); 75 ListNode* node2 = createList(); 76 printList(node2); 77 ListNode* res = mergeList(node1, node2); 78 printList(res); 79 80 return 0; 81 }
(2)递归
Java实现:
package com.mian.demo; import java.util.Scanner; public class MergeTwoListRecur{ public static void main(String[] args) { MergeTwoListRecur mt=new MergeTwoListRecur(); ListNode list1=mt.createList(); ListNode list2=mt.createList(); mt.printList(list1); mt.printList(list2); ListNode node=mt.mergeList(list1,list2); mt.printList(node); } private ListNode mergeList(ListNode list1,ListNode list2){ if(list1==null&&list2==null){ return null; } if(list1==null){ return list2; } if(list2==null){ return list1; } ListNode head=null; if(list1.val<list2.val){ head=list1; head.next=mergeList(list1.next,list2); }else{ head=list2; head.next=mergeList(list1,list2.next); } return head; } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter node value (100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int v){ this.val=v; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode 6 { 7 public: 8 int val; 9 ListNode* next; 10 ListNode(){} 11 ListNode(int x):val(x),next(nullptr){} 12 }; 13 14 ListNode* createList() 15 { 16 int in; 17 ListNode* head = nullptr; 18 cout << "enter list val (enter 100 to quit):"; 19 cin >> in; 20 if (in == 100) 21 return head; 22 else 23 { 24 head = new ListNode(in); 25 head->next = createList(); 26 } 27 return head; 28 } 29 30 void printNode(ListNode* head) 31 { 32 ListNode* p = head; 33 while (p) 34 { 35 cout << p->val << " "; 36 p = p->next; 37 } 38 cout << endl; 39 } 40 41 ListNode* mergeListRecur(ListNode* list1, ListNode* list2) 42 { 43 if (!list1 && !list2) 44 return nullptr; 45 if (list1 == nullptr) 46 return list2; 47 if (list2 == nullptr) 48 return list1; 49 ListNode* head = nullptr; 50 if (list1->val < list2->val) 51 { 52 head = list1; 53 head->next = mergeListRecur(list1->next, list2); 54 } 55 else 56 { 57 head = list2; 58 head->next = mergeListRecur(list1, list2->next); 59 } 60 return head; 61 } 62 63 int main() 64 { 65 ListNode* head1 = createList(); 66 ListNode* head2 = createList(); 67 printNode(head1); 68 printNode(head2); 69 ListNode* head = mergeListRecur(head1, head2); 70 printNode(head); 71 72 return 0; 73 }
18、将数组的后m个数移动为前m个数
Java实现:
package com.mian.demo; public class MoveArrayReverse { public static void main(String[] args) { int[] arr={ 1,2,3,4,5,6,7,8 }; MoveArrayReverse mr=new MoveArrayReverse(); mr.printArray(arr); mr.moveArrayReverse(arr,3); mr.printArray(arr); } private void moveArrayReverse(int[] arr,int n){ int size=arr.length; if(size==0||arr==null){ return; } int m=size-n; reverse(arr,0,m-1); reverse(arr,m,size-1); reverse(arr,0,size-1); } private void reverse(int[] arr,int i,int j){ int size=arr.length; if(size==0||arr==null){ return; } int tmp=0; while(i<j){ tmp=arr[i]; arr[i]=arr[j]; arr[j]=tmp; ++i; --j; } } private void printArray(int[] arr){ int size=arr.length; if(size==0||arr==null){ return; } for(int i=0;i<size-1;++i){ System.out.print(arr[i]+"\t"); } System.out.println(arr[size-1]); } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 4 using namespace std; 5 6 void printArray(vector<int> &arr) 7 { 8 int size = arr.size(); 9 if (size == 0 || arr.empty()) 10 return; 11 for (int i = 0; i < size - 1; ++i) 12 cout << arr[i] << " "; 13 cout << arr[size - 1] << endl; 14 } 15 16 void reverse(vector<int> &arr, int i, int j) 17 { 18 int size = arr.size(); 19 if (size == 0 || arr.empty()) 20 return; 21 int tmp = 0; 22 while (i < j) 23 { 24 tmp = arr[i]; 25 arr[i] = arr[j]; 26 arr[j] = tmp; 27 ++i; 28 --j; 29 } 30 } 31 32 void moveArrayReverse(vector<int> &arr, int n) 33 { 34 int size = arr.size(); 35 if (size == 0 || arr.empty()) 36 return; 37 int m = size - n; 38 reverse(arr, 0, m-1); 39 reverse(arr, m, size-1); 40 reverse(arr, 0, size-1); 41 } 42 43 int main() 44 { 45 vector<int> arr{ 1,2,3,4,5,6,7,8 }; 46 printArray(arr); 47 moveArrayReverse(arr, 3); 48 printArray(arr); 49 50 return 0; 51 }
19、找出数组中出现奇数次的元素:有一个整数数组arr,其中的元素只有一个元素出现奇数次,请找出这个元素。
对于任意一个数k,有k^k = 0,k^0 = k,所以将arr中所有元素进行异或,那么出现次数为偶数的元素异或后都变成了0,出现次数为奇数的元素异或后得到元素本身。
Java实现:
package com.mian.demo; public class OddElement { public static void main(String[] args) { OddElement oe=new OddElement(); int[] arr={1,2,3,4,2,1,4,3,2}; int res=oe.oddElement(arr); System.out.println(res); } private int oddElement(int[] arr){ int res=0; for(int i=0;i<arr.length;++i){ res^=arr[i]; } return res; } }
C++实现:
1 int oddElement(vector<int> &arr) 2 { 3 int res = 0; 4 for (int i = 0; i < arr.size(); ++i) 5 res ^= arr[i]; 6 return res; 7 }
20、使数组中的奇数在左边,偶数在右面
(1)方法一:奇数和偶数之间的相对位置不变
Java实现:
package com.mian.demo; public class OddEven { public static void main(String[] args) { int[] arr={ 0,8,1,2,3,4,5,7,6 }; OddEven oe=new OddEven(); oe.printArray(arr); oe.oddEven(arr); oe.printArray(arr); } private void oddEven(int[] arr){ int size=arr.length; if(size==0||arr==null){ return; } int i=0; int j=0; while(i<size){ while(i<size&&!isEven(arr[i])){ ++i; } j=i+1; while(j<size&&isEven(arr[j])){ ++j; } if(j<size){ int tmp=arr[j]; for(int k=j-1;k>=i;--k){ arr[k+1]=arr[k]; } arr[i++]=tmp; }else{ break; } } } private boolean isEven(int num){ if(num%2==0){ return true; } return false; } private void printArray(int[] arr){ int size=arr.length; if(size==0||arr==null){ return; } for(int i=0;i<size-1;++i){ System.out.print(arr[i]+"\t"); } System.out.println(arr[size-1]); } }
package com.mian.demo; public class OddEvenBubble { public static void main(String[] args) { int[] arr={ 0,8,1,2,3,4,5,7,6 }; OddEvenBubble oeb=new OddEvenBubble(); oeb.printArray(arr); oeb.oddEven(arr); oeb.printArray(arr); } private void oddEven(int[] arr){ int size=arr.length; if(size==0||arr==null){ return; } for(int i=0;i<size;++i){ for(int j=size-1;j>i;--j){ if(arr[j]%2==1&&arr[j-1]%2==0){ arr[j-1]=arr[j-1]+arr[j]; arr[j]=arr[j-1]-arr[j]; arr[j-1]=arr[j-1]-arr[j]; } } } } private void printArray(int[] arr){ int size=arr.length; if(size==0||arr==null){ return; } for(int i=0;i<size-1;++i){ System.out.print(arr[i]+"\t"); } System.out.println(arr[size-1]); } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 4 using namespace std; 5 6 void printArray(vector<int> &arr) 7 { 8 int size = arr.size(); 9 if (size == 0 || arr.empty()) 10 return; 11 for (int i = 0; i < size - 1; ++i) 12 cout << arr[i] << " "; 13 cout << arr[size - 1] << endl; 14 } 15 16 bool isEven(int num) 17 { 18 if (num % 2 == 0) 19 return true; 20 return false; 21 } 22 23 void oddEven(vector<int> &arr) 24 { 25 int size = arr.size(); 26 if (size == 0 || arr.empty()) 27 return; 28 int i = 0; 29 int j = 0; 30 while (i < size) 31 { 32 while (i < size && !isEven(arr[i])) 33 ++i; 34 j = i + 1; 35 while (j < size&&isEven(arr[j])) 36 ++j; 37 if (j < size) 38 { 39 int tmp = arr[j]; 40 for (int k = j - 1; k >= i; --k) 41 arr[k + 1] = arr[k]; 42 arr[i++] = tmp; 43 } 44 else 45 break; 46 } 47 } 48 49 int main() 50 { 51 vector<int> arr{ 0,8,1,2,3,4,5,7,6 }; 52 printArray(arr); 53 oddEven(arr); 54 printArray(arr); 55 56 return 0; 57 }
(2)方法二:不保持奇数和偶数之间的相对位置不变
Java实现:
package com.mian.demo; public class OddEven2 { public static void main(String[] args) { int[] arr={ 0,8,1,2,3,4,5,7,6 }; OddEven2 oe=new OddEven2(); oe.printArray(arr); oe.oddEven(arr); oe.printArray(arr); } private void oddEven(int[] arr){ int size=arr.length; if(size==0||arr==null){ return; } int start=0; int end=size-1; while(start<end){ while(start<end&&!isEven(arr[start])){ ++start; } while(start<end&&isEven(arr[end])){ --end; } swap(arr,start,end); } } private void swap(int[] arr,int a,int b){ int tmp=arr[a]; arr[a]=arr[b]; arr[b]=tmp; } private boolean isEven(int num){ if(num%2==0){ return true; } return false; } private void printArray(int[] arr){ int size=arr.length; if(size==0||arr==null){ return; } for(int i=0;i<size-1;++i){ System.out.print(arr[i]+"\t"); } System.out.println(arr[size-1]); } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 4 using namespace std; 5 6 void printArray(vector<int> &arr) 7 { 8 int size = arr.size(); 9 if (size == 0 || arr.empty()) 10 return; 11 for (int i = 0; i < size - 1; ++i) 12 cout << arr[i] << " "; 13 cout << arr[size - 1] << endl; 14 } 15 16 bool isEven(int num) 17 { 18 if (num % 2 == 0) 19 return true; 20 return false; 21 } 22 23 void swap(vector<int> &arr, int a, int b) 24 { 25 int tmp = arr[a]; 26 arr[a] = arr[b]; 27 arr[b] = tmp; 28 } 29 30 void oddEven(vector<int> &arr) 31 { 32 int size = arr.size(); 33 if (size == 0 || arr.empty()) 34 return; 35 int start = 0; 36 int end = size - 1; 37 while (start < end) 38 { 39 while (start < end && !isEven(arr[start])) 40 ++start; 41 while (start < end&&isEven(arr[end])) 42 --end; 43 swap(arr[start], arr[end]); 44 } 45 } 46 47 int main() 48 { 49 vector<int> arr{ 0,8,1,2,3,4,5,7,6 }; 50 printArray(arr); 51 oddEven(arr); 52 printArray(arr); 53 54 return 0; 55 }
21、数组a[N],1-N-1这(N-1)个数存放在a[N]中,其中某个数重复一次,找出这个数。时间复杂度不超过O(n)
方法一:
Java实现:
package com.mian.demo; public class OnlyRepeateOnce { public static void main(String[] args) { int[] arr={ 1,2,3,3,4,5,6,7 }; OnlyRepeateOnce oto=new OnlyRepeateOnce(); int rep=oto.onlyRepeateOnce(arr); System.out.println(rep); } private int onlyRepeateOnce(int[] arr){ int size=arr.length; if(size==0||arr==null){ return -1; } int res=0; for(int i=0;i<size;++i){ res^=arr[i]; } for(int i=1;i<size;++i){ res^=i; } return res; } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 4 using namespace std; 5 6 int onlyRepeateOnce(vector<int> &arr) 7 { 8 int size = arr.size(); 9 if (size == 0 || arr.empty()) 10 return -1; 11 int res = 0; 12 for (int i = 0; i < size; ++i) 13 res ^= arr[i]; 14 for (int i = 1; i < size; ++i) 15 res ^= i; 16 return res; 17 } 18 19 int main() 20 { 21 vector<int> arr{ 1,2,3,3,4,5,6,7 }; 22 cout << onlyRepeateOnce(arr) << endl; 23 24 return 0; 25 }
方法二:数学推导法: 不重复时sum=1+2+...+ d + (d+1)...+N;现在less=1+2+...+ d + d + (d+1)+...+(N-1)。sum和less都有N个数,由于less中只有一个重复的数字d,则必有1<=d<=(N-1),sum>less。 sum - less = 0+0+...+ 0 + (-d) + 0...0 + N =(N-d)。所以重复的d=N-(sum-less)。
Java实现:
package com.mian.demo; public class OnlyRepeate { public static void main(String[] args) { int[] arr={ 1,2,3,3,4,5,6,7 }; OnlyRepeate or=new OnlyRepeate(); int res=or.onlyRepeate(arr); System.out.println(res); } private int onlyRepeate(int[] arr){ int size=arr.length; if(size==0||arr==null){ return -1; } int sum=0; int less=0; for(int i=1;i<=size;++i){ sum+=i; } for(int i=0;i<size;++i){ less+=arr[i]; } int res=size-(sum-less); return res; } }
22、一个序列先增后减,求峰值
方法一:
Java实现:
package com.mian.demo; public class GetPeek { public static void main(String[] args) { int[] arr={ 3,4,5,6,7,6,4,1,0 }; GetPeek gp=new GetPeek(); gp.getPeek(arr); } private void getPeek(int[] arr){ int size=arr.length; if(size==0||arr==null){ return; } for(int i=1;i<size;++i){ if(arr[i]<arr[i-1]){ System.out.println(arr[i-1]); break; } } } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 4 using namespace std; 5 6 void getPeek(vector<int> &arr) 7 { 8 int size = arr.size(); 9 if (size == 0 || arr.empty()) 10 return; 11 for (int i = 1; i < size; ++i) 12 if (arr[i] < arr[i - 1]) 13 { 14 15 cout << arr[i - 1] << endl; 16 break; 17 } 18 } 19 20 int main() 21 { 22 vector<int> arr{ 3,4,5,6,7,6,4,1,0 }; 23 getPeek(arr); 24 25 return 0; 26 }
方法二:
Java实现:
package com.mian.demo; public class FindPeek { public static void main(String[] args) { int arr[] = { 0,3,6,9,7,5,2,1 }; FindPeek fp=new FindPeek(); int peek=fp.findPeek(arr,8); System.out.println(peek); } private int findPeek(int[] arr,int n){ return helper(arr,n,0,n-1); } private int helper(int[] arr,int n,int low,int high){ int mid=(low+high)>>1; while(low<=high){ if((mid==0||arr[mid-1]<=arr[mid])&&(mid==n-1||arr[mid+1]<=arr[mid])){ return arr[mid]; }else if(mid>0&&arr[mid-1]>arr[mid]){ high=mid-1; }else{ low=mid+1; } } return -1; } }
C++实现:
1 #include<cstdio> 2 3 int helper(int arr[], int n, int low, int high) 4 { 5 int mid = low + (high - low) / 2; 6 while (low <= high) 7 { 8 if ((mid == 0 || arr[mid - 1] <= arr[mid]) && (mid == n - 1 || arr[mid + 1] <= arr[mid])) 9 return arr[mid]; 10 else if (mid > 0 && arr[mid - 1] > arr[mid]) 11 high = mid - 1; 12 else 13 low = mid + 1; 14 } 15 } 16 17 int findPeek(int arr[], int n) 18 { 19 return helper(arr, n, 0, n - 1); 20 } 21 22 int main() 23 { 24 int arr[] = { 0,3,6,9,7,5,2,1 }; 25 printf("%d\n",findPeek(arr, 8)); 26 27 return 0; 28 }
23、用一个for循环打印出一个二维数组
二维数组在内存中默认是按照行存储的,比如一个二维数组{{1,2,3,},{4,5,6}},
它在内存中存储的顺序就是1、2、3、4、5、6,也就是说,对于这6个数组元素,按照从0到5给它们编号的话,
从它们的编号都能推出它们在二维数组中的行号和列号,比如行号即为序号对列数的整数商,列号则为序号对列数取余。
所以别说二维数组了,其它维数组也能用一个for循环打印出来。
Java实现:
package com.mian.demo; public class PrintArray { public static void main(String[] args) { int[][] arr={ {1,2,3,4},{2,3,4,5},{9,6,7,8}}; PrintArray pa=new PrintArray(); pa.printArray(arr,3,4); } private void printArray(int arr[][],int row,int col){ for(int i=0;i<row*col;++i){ System.out.print(arr[i/col][i%col]+"\t"); } System.out.println(); } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 void printArray(int arr[][4], int row, int col) 6 { 7 for (int i = 0; i < row*col; ++i) 8 cout << arr[i / col][i%col] << " "; 9 cout << endl; 10 } 11 12 int main() 13 { 14 int arr[3][4] = { {1,2,3,4},{2,3,4,5},{9,6,7,8}}; 15 printArray(arr, 3, 4); 16 17 return 0; 18 }
24、递归求数组的和
Java实现:
package com.mian.demo; public class RecurSum { public static void main(String[] args) { RecurSum r=new RecurSum(); int[] arr={9,3,1,5,2}; int sum=r.recurSum(arr,arr.length); System.out.println(sum); } private int recurSum(int[] arr,int n){ if(n==0||arr==null){ return 0; } return recurSum(arr,n-1)+arr[n-1]; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 int recurSum(int arr[], int n) 6 { 7 if (n == 0 || arr == nullptr) 8 return 0; 9 return recurSum(arr, n - 1) + arr[n - 1]; 10 } 11 12 int main() 13 { 14 int arr[5] = { 1,2,3,4,5 }; 15 cout << recurSum(arr, 5) << endl; 16 17 return 0; 18 }
25、反转单链表
Java实现:
package com.mian.demo; import java.util.Scanner; public class ReverseList { public static void main(String[] args) { ReverseList rl=new ReverseList(); ListNode head=rl.createList(); rl.printList(head); ListNode last=rl.reverseList(head); rl.printList(last); } private ListNode reverseList(ListNode head){ if(head==null){ return head; } ListNode cur=head; ListNode pre=null; ListNode next=null; while(cur!=null){ next=cur.next; cur.next=pre; pre=cur; cur=next; } return pre; } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter value of list (100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int val){ this.val=val; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode 6 { 7 public: 8 int val; 9 ListNode* next; 10 ListNode(){} 11 ListNode(int x):val(x),next(nullptr){} 12 }; 13 14 ListNode* createList() 15 { 16 int in; 17 ListNode* head = nullptr; 18 cout << "enter list value (enter 100 to quit):"; 19 cin >> in; 20 if (in == 100) 21 return head; 22 else 23 { 24 head = new ListNode(in); 25 head->next = createList(); 26 } 27 return head; 28 } 29 30 void printList(ListNode* head) 31 { 32 if (head == nullptr) 33 return; 34 ListNode* p = head; 35 while (p) 36 { 37 cout << p->val << " "; 38 p = p->next; 39 } 40 cout << endl; 41 } 42 43 ListNode* reverseList(ListNode* head) 44 { 45 if (head == nullptr) 46 return head; 47 ListNode* cur = head; 48 ListNode* pre = nullptr; 49 ListNode* next = nullptr; 50 while (cur) 51 { 52 next = cur->next; 53 cur->next = pre; 54 pre = cur; 55 cur = next; 56 } 57 return pre; 58 } 59 60 int main() 61 { 62 ListNode* head = createList(); 63 printList(head); 64 ListNode* last=reverseList(head); 65 printList(last); 66 67 return 0; 68 }
26、反向输出单链表
Java实现:
package com.mian.demo; import java.util.Scanner; import java.util.Stack; public class ReversePrintList { public static void main(String[] args) { ReversePrintList rpl=new ReversePrintList(); ListNode head=rpl.createList(); rpl.reversePrintList(head); } private void reversePrintList(ListNode head){ if(head==null){ return; } Stack<ListNode> stk=new Stack<>(); ListNode cur=head; while(cur!=null){ stk.push(cur); cur=cur.next; } while(!stk.isEmpty()){ System.out.print(stk.pop().val+"\t"); } } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter value of list (100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int val){ this.val=val; this.next=null; } }
C++实现:
1 #include<iostream> 2 #include<stack> 3 4 using namespace std; 5 6 class ListNode 7 { 8 public: 9 int val; 10 ListNode* next; 11 ListNode(){} 12 ListNode(int x):val(x),next(nullptr){} 13 }; 14 15 ListNode* createList() 16 { 17 int in; 18 ListNode* head = nullptr; 19 cout << "enter list value (enter 100 to quit):"; 20 cin >> in; 21 if (in == 100) 22 return head; 23 else 24 { 25 head = new ListNode(in); 26 head->next = createList(); 27 } 28 return head; 29 } 30 31 void printList(ListNode* head) 32 { 33 if (head == nullptr) 34 return; 35 ListNode* p = head; 36 while (p) 37 { 38 cout << p->val << " "; 39 p = p->next; 40 } 41 cout << endl; 42 } 43 44 void reversePrintList(ListNode* head) 45 { 46 if (head == nullptr) 47 return; 48 stack<ListNode*> stk; 49 ListNode* p = head; 50 while (p) 51 { 52 stk.push(p); 53 p = p->next; 54 } 55 while (!stk.empty()) 56 { 57 ListNode* node = stk.top(); 58 stk.pop(); 59 cout << node->val << " "; 60 } 61 cout << endl; 62 } 63 64 int main() 65 { 66 ListNode* head = createList(); 67 printList(head); 68 reversePrintList(head); 69 70 return 0; 71 }
27、输入一个字符串,输出该字符串中字符的所有组合。举个例子,如果输入abc,它的组合有a、b、c、ab、ac、bc、abc。
方法一:利用位操作来简化题目,即给所有输出方式进行编号(1 ~ 2^n-1)
0 0 1 --> a
0 1 0 --> b
0 1 1 --> ab
1 0 0 --> c
1 0 1 --> ac
1 1 0 --> bc
1 1 1 --> abc
Java实现:
package com.mian.demo; public class PrintAllCombination { public static void main(String[] args) { String s="abc"; PrintAllCombination pac=new PrintAllCombination(); pac.printAllCombination(s); } private void printAllCombination(String s){ int size=s.length(); int comb_count=1<<size; for(int i=1;i<comb_count;++i){ for(int j=0;j<size;++j){ if((i&(1<<j))!=0){ System.out.print(s.charAt(j)+"\t"); } } System.out.println(); } } }
C++实现:
1 #include<stdio.h> 2 #include<string.h> 3 4 void printAllCombination(char *s) 5 { 6 int len = strlen(s); 7 int comb_count = 1 << len; 8 9 for (int i = 1; i < comb_count; ++i) 10 { 11 for (int j = 0; j < len; ++j) 12 if (i&(1 << j)) 13 printf("%c", s[j]); 14 printf("\n"); 15 } 16 } 17 18 int main() 19 { 20 char *s = "abc"; 21 printAllCombination(s); 22 23 return 0; 24 }
方法二:假设想在长度为n的字符串中求m个字符的组合。 先从头扫描字符串的第一个字符。针对第一个字符,有两种选择:一是把这个字符放到组合中去,接下来需要在剩下的n-1个字符中选取m-1个字符;二是不把这个字符放到组合中去,接下来需要在剩下的n-1个字符中选择m个字符。
Java实现:
package com.mian.demo; import java.util.ArrayList; public class Combinations { public static void main(String[] args) { String str="abc"; Combinations cbs=new Combinations(); cbs.combinations(str); } private void combinations(String str){ if(str.isEmpty()){ return; } int size=str.length(); StringBuilder sb=new StringBuilder(); for(int i=0;i<size;++i){ helper(str,0,i,sb); } } private void helper(String str, int index, int num,StringBuilder sb){ if(num==-1){ System.out.println(sb.toString()); return; } if(index==str.length()){ return; } sb.append(str.charAt(index)); helper(str,index+1,num-1,sb); sb.deleteCharAt(sb.length()-1) ; helper(str,index+1,num,sb); } }
C++实现:
1 #include<iostream> 2 #include<cstring> 3 #include<vector> 4 5 using namespace std; 6 7 void helper(char *str, int n, vector<char> &vec) 8 { 9 if (str == nullptr || (n != 0 && *str == '\0')) 10 return; 11 if (n == 0) 12 { 13 for (int i = 0; i < vec.size(); ++i) 14 cout << vec[i] << " "; 15 cout << endl; 16 return; 17 } 18 else 19 { 20 //选择当前元素 21 vec.push_back(*str); 22 helper(str + 1, n - 1, vec); 23 vec.pop_back(); 24 //不选择当前元素 25 helper(str + 1, n, vec); 26 } 27 } 28 29 void combinations(char *str, int len) 30 { 31 if (str == nullptr || len < 1) 32 return; 33 for (int i = 1; i <= len; ++i) 34 { 35 vector<char> vec; 36 helper(str, i, vec); 37 } 38 } 39 40 int main() 41 { 42 char str[] = "abc"; 43 int len = strlen(str); 44 combinations(str, len); 45 46 return 0; 47 }
28、在两个数组中寻找两个数的和等于指定的数值
方法一:
Java实现:
package com.mian.demo; import java.util.Arrays; public class TargetInTwoArray { public static void main(String[] args) { int[] arr1={ 1,2,0,9,4,7,3 }; int[] arr2={ 9,4,3,2,1,0,8 }; TargetInTwoArray tns=new TargetInTwoArray(); int target=6; tns.twoNumSumInArray(arr1,arr2,target); } private void twoNumSumInArray(int[] arr1,int[] arr2,int target){ int size1=arr1.length; int size2=arr2.length; if(arr1==null||size1==0||arr2==null||size2==0){ return; } Arrays.sort(arr1); Arrays.sort(arr2); int i=0; int j=size2-1; while(i<size1&&j>=0){ if(arr1[i]+arr2[j]==target){ System.out.println(arr1[i]+"\t"+arr2[j]); ++i; --j; }else if(arr1[i]+arr2[j]>target){ --j; }else{ ++i; } } } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 5 using namespace std; 6 7 void twoNumberSum(vector<int> &arr1, vector<int> &arr2, int target) 8 { 9 int size1 = arr1.size(); 10 int size2 = arr2.size(); 11 if (arr1.empty() || size1 == 0 || arr2.empty() || size2 == 0) 12 return; 13 sort(arr1.begin(), arr1.end()); 14 sort(arr2.begin(), arr2.end()); 15 int i = 0; 16 int j = size2 - 1; 17 while (i < size1&&j >= 0) 18 { 19 if (arr1[i] + arr2[j] == target) 20 { 21 cout << arr1[i] << " " << arr2[j] << endl; 22 ++i; 23 --j; 24 } 25 else if (arr1[i] + arr2[j] > target) 26 --j; 27 else 28 ++i; 29 } 30 } 31 32 int main() 33 { 34 vector<int> arr1{ 1,2,0,9,4,7,3 }; 35 vector<int> arr2{ 9,4,3,2,1,0,8 }; 36 twoNumberSum(arr1, arr2, 6); 37 38 return 0; 39 }
方法二:
Java实现:
package com.mian.demo; import java.util.Arrays; public class TargetInTwoArray2 { public static void main(String[] args) { int[] arr1={ 1,2,0,9,4,7,3 }; int[] arr2={ 9,4,3,2,1,0,8 }; TargetInTwoArray2 tns=new TargetInTwoArray2(); int target=6; tns.twoNumSumInArray(arr1,arr2,target); } private void twoNumSumInArray(int[] arr1,int[] arr2,int target){ int size1=arr1.length; int size2=arr2.length; if(arr1==null||size1==0||arr2==null||size2==0){ return; } Arrays.sort(arr1); for(int i=0;i<size2;++i){ if(binarySearch(arr1,target-arr2[i])){ System.out.println(arr2[i]+"\t"+(target-arr2[i])); } } } private boolean binarySearch(int[] arr,int target){ int low=0; int high=arr.length-1; int mid=0; while(low<=high){ mid=(low+high)>>1; if(arr[mid]>target){ high=mid-1; }else if(arr[mid]<target){ low=mid+1; }else{ return true; } } return false; } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 5 using namespace std; 6 7 bool search(vector<int> &arr, int val) 8 { 9 int low = 0; 10 int high = arr.size() - 1; 11 int mid = 0; 12 while (low <= high) 13 { 14 mid = (low + high) / 2; 15 if (arr[mid] > val) 16 high = mid - 1; 17 else if (arr[mid] < val) 18 low = mid + 1; 19 else 20 return true; 21 } 22 return false; 23 } 24 25 void twoNumSum(vector<int> &arr1, vector<int> &arr2, int target) 26 { 27 int size1 = arr1.size(); 28 int size2 = arr2.size(); 29 if (size1 == 0 || size2 == 0 || arr1.empty() || arr2.empty()) 30 return; 31 sort(arr1.begin(), arr1.end()); 32 for (int i = 0; i < size2; ++i) 33 if (search(arr1, target - arr2[i])) 34 cout << arr2[i] << " " << (target - arr2[i]) << endl; 35 } 36 37 int main() 38 { 39 vector<int> arr1{ 1,2,0,9,4,7,3 }; 40 vector<int> arr2{ 9,4,3,2,1,0,8 }; 41 twoNumSum(arr1, arr2, 6); 42 43 return 0; 44 }
29、不用两个指针求有环单链表的结点数
(1)删除计数过的结点
Java实现:
package com.mian.demo; import java.util.Scanner; public class CountNode { public static void main(String[] args) { CountNode cn=new CountNode(); ListNode head=cn.createList(); cn.printList(head); ListNode last=head; while(last.next!=null){ last=last.next; } ListNode cur=head; ListNode node=cur.next.next.next; last.next=node; int count=cn.countNode(head); System.out.println(count); } private int countNode(ListNode head){ if(head==null){ return 0; } ListNode cur=head; int cnt=0; while(cur.next!=null){ cur=cur.next; head.next=null; head=cur; ++cnt; } return cnt; } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter value of list (100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int val){ this.val=val; this.next=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class ListNode 6 { 7 public: 8 int val; 9 ListNode* next; 10 ListNode(){} 11 ListNode(int x):val(x),next(nullptr){} 12 }; 13 14 ListNode* createNode() 15 { 16 int in; 17 ListNode* head = nullptr; 18 cout << "enter list value (enter 100 to quit):"; 19 cin >> in; 20 if (in == 100) 21 return head; 22 else 23 { 24 head = new ListNode(in); 25 head->next = createNode(); 26 } 27 return head; 28 } 29 30 void printList(ListNode* head) 31 { 32 if (head == nullptr) 33 return; 34 ListNode* p = head; 35 while (p) 36 { 37 cout << p->val << " "; 38 p = p->next; 39 } 40 cout << endl; 41 } 42 43 int countNode(ListNode* head) 44 { 45 if (head == nullptr) 46 return 0; 47 ListNode* p = head; 48 int cnt = 0; 49 while (p->next) 50 { 51 p = p->next; 52 head->next = nullptr; 53 head = p; 54 ++cnt; 55 } 56 return cnt; 57 } 58 59 int main() 60 { 61 ListNode* head = createNode(); 62 printList(head); 63 ListNode* p = head->next->next; 64 ListNode* last = head; 65 while (last->next) 66 last = last->next; 67 last->next = p; 68 cout << countNode(head) << endl; 69 70 return 0; 71 }
(2)map记录计数过的结点
Java实现:
package com.mian.demo; import java.util.HashMap; import java.util.Scanner; public class CountNodeMap { public static void main(String[] args) { CountNodeMap cnm=new CountNodeMap(); ListNode head=cnm.createList(); cnm.printList(head); ListNode last=head; while(last.next!=null){ last=last.next; } ListNode cur=head; ListNode node=cur.next.next.next; last.next=node; int count=cnm.countNode(head); System.out.println(count); } private int countNode(ListNode head){ if(head==null){ return 0; } ListNode cur=head; int cnt=0; HashMap<Integer,Integer> map=new HashMap<>(); while(cur!=null){ if(!map.containsKey(cur.val)){ ++cnt; map.put(cur.val,cur.val); }else{ break; } cur=cur.next; } return cnt; } private ListNode createList(){ int val; ListNode head=null; System.out.println("enter value of list (100 to quit):"); Scanner sc=new Scanner(System.in); val=sc.nextInt(); if(val==100){ return head; }else{ head=new ListNode(val); head.next=createList(); } return head; } private void printList(ListNode head){ if(head==null){ return; } ListNode cur=head; while(cur!=null){ System.out.print(cur.val+"\t"); cur=cur.next; } System.out.println(); } } class ListNode{ public int val; ListNode next; ListNode(){} ListNode(int val){ this.val=val; this.next=null; } }
C++实现:
1 #include<iostream> 2 #include<unordered_map> 3 4 using namespace std; 5 6 class ListNode 7 { 8 public: 9 int val; 10 ListNode* next; 11 ListNode(){} 12 ListNode(int x):val(x),next(nullptr){} 13 }; 14 15 ListNode* createNode() 16 { 17 int in; 18 ListNode* head = nullptr; 19 cout << "enter list value (enter 100 to quit):"; 20 cin >> in; 21 if (in == 100) 22 return head; 23 else 24 { 25 head = new ListNode(in); 26 head->next = createNode(); 27 } 28 return head; 29 } 30 31 void printList(ListNode* head) 32 { 33 if (head == nullptr) 34 return; 35 ListNode* p = head; 36 while (p) 37 { 38 cout << p->val << " "; 39 p = p->next; 40 } 41 cout << endl; 42 } 43 44 int countNode(ListNode* head) 45 { 46 if (head == nullptr) 47 return 0; 48 ListNode* p = head; 49 int cnt = 0; 50 unordered_map<ListNode*, int> m; 51 while (p) 52 { 53 if (m.insert(pair<ListNode*, int>(p, 1)).second) 54 ++cnt; 55 else 56 break; 57 p = p->next; 58 } 59 return cnt; 60 } 61 62 int main() 63 { 64 ListNode* head = createNode(); 65 printList(head); 66 ListNode* p = head->next->next; 67 ListNode* last = head; 68 while (last->next) 69 last = last->next; 70 last->next = p; 71 cout << countNode(head) << endl; 72 73 return 0; 74 }
30、数组第一个出现两次的数
Java实现:
package com.mian.demo; import java.util.HashMap; public class FindNumber { public static void main(String[] args) { int[] arr={ 9,0,3,2,1,4,3,2,3,0,5 }; FindNumber fn=new FindNumber(); int res=fn.findNumber(arr); System.out.println(res); } private int findNumber(int[] arr){ int size=arr.length; if(size<2||arr==null){ return -1; } HashMap<Integer,Integer> map=new HashMap<>(); for(int i=0;i<size;++i){ if(map.containsKey(arr[i])){ map.put(arr[i],map.get(arr[i])+1); }else{ map.put(arr[i],1); } } for(int i=0;i<size;++i){ if(map.get(arr[i])==2){ return arr[i]; } } return -1; } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 #include<unordered_map> 4 5 using namespace std; 6 7 int findTwoNumber(vector<int> &arr) 8 { 9 int size = arr.size(); 10 if (size < 2 || arr.empty()) 11 return -1; 12 unordered_map<int, int> m; 13 for (int i = 0; i < size; ++i) 14 { 15 auto it = m.find(arr[i]); 16 if (it != m.end()) 17 ++it->second; 18 else 19 m[arr[i]] = 1; 20 } 21 for (int i = 0; i < size; ++i) 22 if (m[arr[i]] == 2) 23 return arr[i]; 24 return -1; 25 } 26 27 int main() 28 { 29 vector<int> arr{ 9,0,3,2,1,4,3,2,3,0,5 }; 30 cout << findTwoNumber(arr) << endl; 31 32 return 0; 33 }
31、求第一次重复的字符
求第一次重复的字符,只需遍历一遍字符串,遍历的过程中判断当前遇到的字符之前是否出现过,如果出现过则返回,否则继续读下面的字符。如kfdaaak的第一个出现重复的字符是a而不是k。
Java实现:
package com.mian.demo; import java.util.HashMap; public class FirstRepeateChar { public static void main(String[] args) { String str="kfdaaak"; FirstRepeateChar fr=new FirstRepeateChar(); char c=fr.firstRepeateChar(str); System.out.println(c); } private char firstRepeateChar(String str){ int size=str.length(); if(size<2||str.isEmpty()){ return ' '; } HashMap<Character,Integer> map=new HashMap<>(); for(int i=0;i<size;++i){ if(map.containsKey(str.charAt(i))){ return str.charAt(i); }else{ map.put(str.charAt(i),1); } } return ' '; } }
package com.mian.demo; public class FirstRepeateCharHash { public static void main(String[] args) { FirstRepeateCharHash fr=new FirstRepeateCharHash(); String str="kfdaaak"; char c=fr.firstRepeateCharHash(str); System.out.println(c); } private char firstRepeateCharHash(String str){ int size=str.length(); if(size<2||str.isEmpty()){ return ' '; } int[] hash=new int[256]; for(int i=0;i<size;++i){ ++hash[str.charAt(i)]; if(hash[str.charAt(i)]==2){ return str.charAt(i); } } return ' '; } }
C++实现:
1 #include<iostream> 2 #include<string> 3 #include<unordered_map> 4 5 using namespace std; 6 7 char firstRepeatChar(string &str) 8 { 9 int size = str.size(); 10 if (size < 2 || str.empty()) 11 return ' '; 12 unordered_map<char, int> m; 13 for (int i = 0; i < size; ++i) 14 { 15 auto it = m.find(str[i]); 16 if (it != m.end()) 17 return str[i]; 18 else 19 m[str[i]] = 1; 20 } 21 return ' '; 22 } 23 24 int main() 25 { 26 string str = "kfdaaak"; 27 cout << firstRepeatChar(str) << endl; 28 29 return 0; 30 }
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 5 using namespace std; 6 7 char firstRepeatChar(string &str) 8 { 9 int size = str.size(); 10 if (size < 2 || str.empty()) 11 return ' '; 12 vector<int> hash(256, 0); 13 for (int i = 0; i < size; ++i) 14 { 15 ++hash[(int)str[i]]; 16 if (hash[(int)str[i]] == 2) 17 return str[i]; 18 } 19 return ' '; 20 } 21 22 int main() 23 { 24 string str = "kfdaaak"; 25 cout << firstRepeatChar(str) << endl; 26 27 return 0; 28 }
32、求第一个只出现一次的字符
遍历两次字符串,第一次遍历是把每个字符都存储到hash表中,对应的值是出现的次数。第二次遍历则是第一个只出现一次的字符。
Java实现:
package com.mian.demo; public class OnlyOnceChar { public static void main(String[] args) { OnlyOnceChar oc=new OnlyOnceChar(); String str="kfdaaak"; char c=oc.onlyOnceChar(str); System.out.println(c); } private char onlyOnceChar(String str){ int size=str.length(); if(size==0||str.isEmpty()){ return ' '; } int[] hash=new int[256]; for(int i=0;i<size;++i){ ++hash[str.charAt(i)]; } for(int i=0;i<size;++i){ if(hash[str.charAt(i)]==1){ return str.charAt(i); } } return ' '; } }
package com.mian.demo; import java.util.HashMap; public class OnlyOnceCharMap { public static void main(String[] args) { OnlyOnceCharMap om=new OnlyOnceCharMap(); String str="kfdaaak"; char c=om.onlyOnceChar(str); System.out.println(c); } private char onlyOnceChar(String str){ int size=str.length(); if(size==0||str.isEmpty()){ return ' '; } HashMap<Character,Integer> map=new HashMap<>(); for(int i=0;i<size;++i){ if(map.containsKey(str.charAt(i))){ map.put(str.charAt(i),map.get(str.charAt(i))+1); }else{ map.put(str.charAt(i),1); } } for(int i=0;i<size;++i){ if(map.get(str.charAt(i))==1){ return str.charAt(i); } } return ' '; } }
C++实现:
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 5 using namespace std; 6 7 char onlyOnceChar(string &str) 8 { 9 int size = str.size(); 10 if (size ==0 || str.empty()) 11 return ' '; 12 vector<int> hash(256, 0); 13 for (int i = 0; i < size; ++i) 14 ++hash[(int)str[i]]; 15 for (int i = 0; i < size; ++i) 16 if (hash[(int)str[i]] == 1) 17 return str[i]; 18 return ' '; 19 } 20 21 int main() 22 { 23 string str = "kfdaaak"; 24 cout << onlyOnceChar(str) << endl; 25 26 return 0; 27 }
1 #include<iostream> 2 #include<string> 3 #include<unordered_map> 4 5 using namespace std; 6 7 char onlyOnceChar(string &str) 8 { 9 int size = str.size(); 10 if (size ==0 || str.empty()) 11 return ' '; 12 unordered_map<char, int> m; 13 for (char c : str) 14 { 15 auto it = m.find(c); 16 if (it != m.end()) 17 ++it->second; 18 else 19 m[c] = 1; 20 } 21 for (char c : str) 22 if (m[c] == 1) 23 return c; 24 return ' '; 25 } 26 27 int main() 28 { 29 string str = "kfdaaak"; 30 cout << onlyOnceChar(str) << endl; 31 32 return 0; 33 }
33、计算给定的日期是一年中的第多少天
Java实现:
package com.mian.demo; import java.util.Scanner; public class GetDay { public static void main(String[] args) { GetDay gd=new GetDay(); Scanner sc=new Scanner(System.in); int year=sc.nextInt(); int month=sc.nextInt(); int day=sc.nextInt(); int days=gd.getDay(year,month,day); System.out.println(days); } private int getDay(int year,int month,int day){ int res=0; int d=0; for(int i=1;i<month;++i){ switch (i){ case 1: case 3: case 5: case 7: case 8: case 10: case 12: d=31; res+=d; break; case 2: if((year%4==0&&year%100==0)||year%400==0){ d=29; res+=d; }else{ d=28; res+=d; } break; case 4: case 6: case 9: case 11: d=30; res+=d; break; } } return res+day; } }
C++实现:
#include<iostream> using namespace std; int getDay(int year, int month, int day) { int res = 0; int d = 0; for (int i = 1; i < month; ++i) { switch (i) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: d = 31; res += d; break; case 2: if ((year % 4 == 0 && year % 100==0) || year % 400 == 0) { d = 29; res += d; } else { d = 28; res += d; } break; case 4: case 6: case 9: case 11: d = 30; res += d; break; } } return res + day; } int main() { int year, month, day; cout << "enter year month day:"; cin >> year >> month >> day; cout << getDay(year, month, day) << endl; return 0; }
34、求A的B次的后三位
乘积的最后三位的值只与乘数和被乘数的后三位有关,与乘数和被乘数的高位无关。
Java实现:
package com.mian.algorithm; public class LastThree { public static void main(String[] args) { LastThree lt=new LastThree(); int res=lt.lastThree(23,9); System.out.println(res); } private int lastThree(int n,int m){ int last=1; for(int i=1;i<=m;++i){ last=(last*n)%1000; } return last; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 int lastThree(int n, int m) 6 { 7 int last = 1; 8 for (int i = 1; i <= m; ++i) 9 last = (last*n) % 1000; 10 return last; 11 } 12 13 int main() 14 { 15 cout << lastThree(23, 9) << endl; 16 17 return 0; 18 }
35、最长公共子序列(不连续)时间复杂度O(m*n)
Java实现:
package com.mian.demo; import java.util.Scanner; public class LCS { public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("enter two string:"); String s1=sc.next(); String s2=sc.next(); int m=s1.length(); int n=s2.length(); int[][] b=new int[m][n]; LCS lcs=new LCS(); System.out.println("Length of LCS is "+lcs.lengthLCS(s1,s2,b,m,n)); System.out.println("打印其中的一个LCS:"); lcs.printLCS(b,s1,m,n); } private int lengthLCS(String s1,String s2,int[][] b,int m,int n){ int[][] c=new int[m+1][n+1]; for(int i=0;i<=m;++i){ for(int j=0;j<=n;++j){ if(i==0||j==0){ c[i][j]=0; }else{ if(s1.charAt(i-1)==s2.charAt(j-1)){ c[i][j]=c[i-1][j-1]+1; b[i-1][j-1]=1; }else{ if(c[i-1][j]>=c[i][j-1]){ c[i][j]=c[i-1][j]; b[i-1][j-1]=0; }else{ c[i][j]=c[i][j-1]; b[i-1][j-1]=-1; } } } } } return c[m][n]; } private void printLCS(int[][] b,String s,int i,int j){ if(i==0||j==0){ return; } if(b[i-1][j-1]==1){ printLCS(b,s,i-1,j-1); System.out.print(s.charAt(i-1)); }else if(b[i-1][j-1]==0){ printLCS(b,s,i-1,j); }else{ printLCS(b,s,i,j-1); } } }
C++实现:
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 5 using namespace std; 6 //最长公共子序列(不连续)时间复杂度O(m*n) 7 int length_LCS(string s1, string s2, vector<vector<int>> &c, vector<vector<int>> &b,int m, int n) //输出LCS的长度 8 { 9 /*处理其他行和列*/ 10 for (int i = 0; i <= m; i++) 11 { 12 for (int j = 0; j <= n; j++) 13 { 14 /*处理特殊的0行和0列*/ 15 if (i == 0 || j == 0) 16 c[i][j] = 0; 17 else 18 { 19 if (s1[i - 1] == s2[j - 1]) 20 { 21 c[i][j] = c[i - 1][j - 1] + 1; 22 b[i - 1][j - 1] = 1; 23 } 24 else 25 { 26 if (c[i - 1][j] >= c[i][j - 1]) 27 { 28 c[i][j] = c[i - 1][j]; 29 b[i - 1][j - 1] = 0; 30 } 31 else 32 { 33 c[i][j] = c[i][j - 1]; 34 b[i - 1][j - 1] = -1; 35 } 36 } 37 } 38 } 39 } 40 return c[m][n]; 41 } 42 43 void Print_LCS(vector<vector<int>> &b, string x, int i, int j) //输出LCS序列 44 { 45 if (i == 0 || j == 0) 46 return; 47 if (b[i - 1][j - 1] == 1) 48 { 49 Print_LCS(b, x, i - 1, j - 1); 50 cout << x[i - 1]; 51 } 52 else if (b[i - 1][j - 1] == 0) 53 { 54 Print_LCS(b, x, i - 1, j); 55 } 56 else 57 Print_LCS(b, x, i, j - 1); 58 } 59 60 int main() 61 { 62 string s1, s2; 63 cout << "请输入两个序列:" << endl; 64 cin >> s1 >> s2; 65 int m = s1.length(), n = s2.length(); 66 vector<vector<int>> c(m+1, vector<int>(n + 1)); 67 vector<vector<int>> b(m, vector<int>(n)); 68 cout << "LCS的长度:" << length_LCS(s1, s2, c, b, m, n) << endl; 69 cout << "打印其中的一个LCS:"; 70 Print_LCS(b, s1, m, n); 71 cout << endl; 72 73 return 0; 74 }
36、最长公共子字符串:类似最长子序列,只是公共子字符串要求必须是连续的。
Java实现:
package com.mian.demo; import org.bouncycastle.util.Arrays; public class LongSubstring { public static void main(String[] args) { LongSubstring ls=new LongSubstring(); String str1="123456"; String str2="14568"; int[][] arr=new int[str1.length()+1][str2.length()+1]; for(int i=0;i<=str1.length();++i){ Arrays.fill(arr[i],-1); } int res=ls.longString(str1,str2,arr); System.out.println("result = "+res); ls.printLCS(arr,str1,str1.length(),str2.length()); } private int longString(String str1,String str2,int[][] arr){ int size1=str1.length(); int size2=str2.length(); int max=0; int[][] dp=new int[size1+1][size2+1]; for(int i=0;i<=size1;++i){ for(int j=0;j<=size2;++j){ if(i==0||j==0){ dp[i][j]=0; }else if(str1.charAt(i-1)==str2.charAt(j-1)){ dp[i][j]=dp[i-1][j-1]+1; arr[i][j]=1; max=dp[i][j]>max?dp[i][j]:max; } } } return max; } private void printLCS(int[][] arr,String str,int i,int j){ if(i==0||j==0){ return; } if(arr[i][j]==1){ printLCS(arr,str,i-1,j-1); System.out.print(str.charAt(i-1)); }else if(arr[i][j]==0){ printLCS(arr,str,i-1,j); }else{ printLCS(arr,str,i,j-1); } } }
C++实现:
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 5 using namespace std; 6 7 int long_substr(string str1, string str2, vector<vector<int>>& vec) { 8 int size1 = str1.size(); 9 int size2 = str2.size(); 10 int max = 0; //记录最长公共子串长度 11 vector<vector<int>> dp(size1 + 1, vector<int>(size2 + 1, 0)); 12 for (int i = 0; i <= size1; i++) { 13 for (int j = 0; j <= size2; j++) { 14 if (i == 0 || j == 0) { 15 dp[i][j] = 0; 16 } 17 else if (str1[i - 1] == str2[j - 1]) { 18 dp[i][j] = dp[i - 1][j - 1] + 1; 19 vec[i][j] = 1; 20 max = dp[i][j] > max ? dp[i][j] : max; 21 } 22 } 23 } 24 return max; 25 } 26 27 void print_lcs(vector<vector<int>>& vec, string str, int i, int j) 28 { 29 if (i == 0 || j == 0) 30 return; 31 if (vec[i][j] == 1) 32 { 33 print_lcs(vec, str, i - 1, j - 1); 34 printf("%c", str[i - 1]); 35 } 36 else if (vec[i][j] == 0) 37 { 38 print_lcs(vec, str, i - 1, j); 39 } 40 else 41 { 42 print_lcs(vec, str, i, j - 1); 43 } 44 } 45 int main() 46 { 47 string str1 = "123456"; 48 string str2 = "14568"; 49 vector<vector<int>> vec(str1.size() + 1, vector<int>(str2.size() + 1, -1)); 50 int result = long_substr(str1, str2, vec); 51 52 cout << "result = " << result << endl; 53 54 print_lcs(vec, str1, str1.size(), str2.size()); 55 56 return 0; 57 }
37、最长不重复子串
Java实现:
package com.mian.demo; import java.util.Arrays; import java.util.HashMap; public class LongestNoRepeateSubstring { public static void main(String[] args) { LongestNoRepeateSubstring lr=new LongestNoRepeateSubstring(); String str="120135435"; System.out.println(lr.longestNoRepeateSubstrMap(str)); System.out.println(lr.longestNoRepeateSubstr(str)); } private String longestNoRepeateSubstrMap(String str){ int size=str.length(); if(size==0||str.isEmpty()){ return ""; } HashMap<Character,Integer> map=new HashMap<>(); int startIndex=-1; int originIndex=-1; int maxLength=0; for(int i=0;i<size;++i){ if(map.containsKey(str.charAt(i))&&map.get(str.charAt(i))>startIndex){ startIndex=map.get(str.charAt(i)); }else{ if(i-startIndex>maxLength){ maxLength=i-startIndex; originIndex=startIndex; } } map.put(str.charAt(i),i); } return str.substring(originIndex+1,originIndex+maxLength+1); } private String longestNoRepeateSubstr(String str){ int size=str.length(); if(size==0||str.isEmpty()){ return ""; } int[] hash=new int[256]; Arrays.fill(hash,-1); int startIndex=-1; int originIndex=startIndex; int maxLength=0; for(int i=0;i<size;++i){ if(hash[str.charAt(i)]>startIndex){ startIndex=hash[str.charAt(i)]; } if(i-startIndex>maxLength){ maxLength=i-startIndex; originIndex=startIndex; } hash[str.charAt(i)]=i; } return str.substring(originIndex+1,originIndex+maxLength+1); } }
C++实现:
1 #include<iostream> 2 #include<string> 3 #include<unordered_map> 4 5 using namespace std; 6 7 /*解法一*/ 8 string longestNoRepeateSubstrMap(string &str) 9 { 10 int size = str.size(); 11 if (size == 0 || str.empty()) 12 return ""; 13 unordered_map<char, int> m; 14 int start_index = -1; 15 int origin_index = -1; 16 int max_len = 0; 17 for (int i=0;i<size;++i) 18 { 19 auto it = m.find(str[i]); 20 if (it != m.end()) 21 if (it->second > start_index) 22 start_index = it->second; 23 if(i-start_index>max_len) 24 { 25 max_len = i - start_index; 26 origin_index = start_index; 27 } 28 m[str[i]] = i; 29 } 30 return str.substr(origin_index + 1, max_len); 31 } 32 33 /*解法二*/ 34 string longestNoRepeateSubstrMap2(string &str) 35 { 36 int size = str.size(); 37 if (str.empty() || size == 0) 38 return ""; 39 unordered_map<char, int> m; 40 int start_index = -1; 41 int origin_index = start_index; 42 int max_len = 0; 43 for (int i = 0; i < size; ++i) 44 { 45 if (!m.insert(pair<char, int>(str[i], 1)).second) 46 { 47 int index = m[str[i]]; 48 if (index > start_index) 49 start_index = index; 50 } 51 if (i - start_index > max_len) 52 { 53 max_len = i - start_index; 54 origin_index = start_index; 55 } 56 m[str[i]] = i; 57 } 58 return str.substr(origin_index + 1, max_len); 59 } 60 61 /*解法三*/ 62 string longestNoRepeateSubstr(string &str) 63 { 64 int size = str.size(); 65 if (str.empty() || size == 0) 66 return ""; 67 vector<int> help(256, -1); 68 int start_index = -1; 69 int origin_index = start_index; 70 int max_len = 0; 71 for (int i = 0; i < size; ++i) 72 { 73 if (help[str[i]] > start_index) 74 start_index = help[str[i]]; 75 if (i - start_index > max_len) 76 { 77 max_len = i - start_index; 78 origin_index = start_index; 79 } 80 help[str[i]] = i; 81 } 82 return str.substr(origin_index + 1, max_len); 83 } 84 85 int main() 86 { 87 string str = "absasdfdew"; 88 cout << longestNoRepeateSubstrMap(str) << endl; 89 cout << longestNoRepeateSubstrMap2(str) << endl; 90 cout << longestNoRepeateSubstr(str) << endl; 91 92 return 0; 93 }
38、M进制与N进制的转换
Java实现:
package com.mian.demo; public class MtoN { public static void main(String[] args) { MtoN mn=new MtoN(); String str="9C"; String res=mn.MtoN(str,16,8); System.out.println(res); } private String MtoN(String str,int m,int n){ int[] charToNum=new int[256]; int[] numToChar=new int[256]; for(int i=0;i<=9;++i){ charToNum['0'+i]=i; numToChar[i]='0'+i; } for(int i=10;i<=35;++i){ charToNum['A'+i-10]=i; numToChar[i]='A'+i-10; } int realValue=0; int maxChar=numToChar[m]; for(int i=0;i<str.length();++i){ if(str.charAt(i)>=maxChar){ return "Error Input"; } realValue=realValue*m+charToNum[str.charAt(i)]; } String s=""; while(realValue!=0){ char ch=(char)numToChar[realValue%n]; s=ch+s; realValue=realValue/n; } return s; } }
C++实现:
1 #include<iostream> 2 #include<string> 3 4 using namespace std; 5 6 string MtoN(string &str, int m, int n) 7 { 8 int charToNum[256]; //通过字符找到数字 9 int numToChar[256]; //通过数字找到字符 10 for (int i = 0; i <= 9; i++) 11 { 12 charToNum['0' + i] = i; 13 numToChar[i] = '0' + i; 14 } 15 for (int i = 10; i <= 35; i++) 16 { 17 charToNum['A' + i - 10] = i; 18 numToChar[i] = 'A' + i - 10; 19 } 20 21 int realValue = 0; //十进制数 22 int maxChar = numToChar[m]; //m进制每位能表示的最大值对应的字符 23 for (int i = 0; i < str.length(); i++) //输入字符串str转换为十进制 24 { 25 if (str[i] >= maxChar) 26 return "Error input!"; 27 realValue = realValue*m + charToNum[str[i]]; 28 } 29 30 string s; 31 while (realValue) 32 { 33 char ch = numToChar[realValue%n]; 34 s = ch + s; //逆序将得到的每一位存储到s中,逆序什么意思呢?比如realVaule的十进制值为128, 35 realValue = realValue / n; //现在需转换为二进制,如果是s=s+char,得到的s为00000001,如果是s=ch+s,s的结果为10000000,因为此时是将每一个ch字符添加到s的前面 36 } 37 return s; 38 } 39 40 int main() 41 { 42 string str = "9C"; 43 cout << MtoN(str, 16, 8) << endl; 44 45 return 0; 46 }
39、字符串中出现次数最多那个字符
Java实现:
package com.mian.demo; public class MaxCountChar { public static void main(String[] args) { MaxCountChar mc=new MaxCountChar(); String str="agdfsdadfew"; char c=mc.maxCountChar(str); System.out.println(c); } private char maxCountChar(String str){ char res=' '; int size=str.length(); if(size==0||str.isEmpty()){ return res; } int[] hash=new int[256]; for(int i=0;i<size;++i){ ++hash[str.charAt(i)]; } int max=Integer.MIN_VALUE; for(int i=0;i<size;++i){ if(max<hash[str.charAt(i)]){ max=hash[str.charAt(i)]; res=str.charAt(i); } } return res; } }
C++实现:
1 char maxCountChar(string &str) 2 { 3 char res = ' '; 4 int size = str.size(); 5 if (str.empty() || size == 0) 6 return res; 7 vector<int> help(256, 0); 8 for (int i = 0; i < size; ++i) 9 help[str[i]]++; 10 int max = INT_MIN; 11 for(int i=0;i<size;++i) 12 if (max < help[str[i]]) 13 { 14 max = help[str[i]]; 15 res = str[i]; 16 } 17 return res; 18 }
40、找出数组的第K大的数
Java实现:
package com.mian.demo; public class MaxK { public static void main(String[] args) { MaxK mk=new MaxK(); int[] arr={ 6,4,1,3,2,5,7 }; int res=mk.maxK(arr,3); System.out.println(res); } private int maxK(int[] arr,int k){ int size=arr.length; if(arr==null||size==0||k<=0||k>=size){ return -1; } int low=0; int high=size-1; int target=size-k; int index=partition(arr,low,high); while(index!=target){ if(index>target){ high=index-1; index=partition(arr,low,high); }else{ low=index+1; index=partition(arr,low,high); } } return arr[target]; } private int partition(int[] arr,int low,int high){ int pivot=arr[low]; while(low<high){ while(low<high&&arr[high]>=pivot){ --high; } arr[low]=arr[high]; while(low<high&&arr[low]<=pivot){ ++low; } arr[high]=arr[low]; } arr[low]=pivot; return low; } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 4 using namespace std; 5 6 int partition(vector<int> &arr, int start, int end) 7 { 8 int low = start; 9 int high = end; 10 int key = arr[low]; 11 while (low < high) 12 { 13 while (low < high&&arr[high] >= key) 14 high--; 15 arr[low] = arr[high]; 16 while (low < high&&arr[low] <= key) 17 low++; 18 arr[high] = arr[low]; 19 } 20 arr[low] = key; 21 return low; 22 } 23 24 int maxK(vector<int> &arr, int k) 25 { 26 int size = arr.size(); 27 if (arr.empty() || size == 0 || k <= 0 || k >= size) 28 return -1; 29 int low = 0; 30 int high = size - 1; 31 int target = size - k; 32 int index = partition(arr, low, high); 33 while (index != target) 34 { 35 if (index > target) 36 { 37 high = index - 1; 38 index = partition(arr, low, high); 39 } 40 else 41 { 42 low = index + 1; 43 index = partition(arr, low, high); 44 } 45 } 46 return arr[target]; 47 } 48 49 int main() 50 { 51 vector<int> arr{ 6,4,1,3,2,5,7 }; 52 cout << maxK(arr, 3) << endl; 53 54 return 0; 55 }
41、找出数组中第二大的数
Java实现:
package com.mian.demo; public class SecondMax { public static void main(String[] args) { SecondMax sm=new SecondMax(); int[] arr={ 6,4,1,3,2,5,7 }; int secondMax=sm.secondMax(arr); System.out.println(secondMax); } private int secondMax(int[] arr){ int size=arr.length; if(size==0||arr==null){ return Integer.MIN_VALUE; } int max=Integer.MIN_VALUE; int secondMax=Integer.MAX_VALUE; for(int i=0;i<size;++i){ if(arr[i]>max){ secondMax=max; max=arr[i]; }else{ if(arr[i]>secondMax){ secondMax=arr[i]; } } } return secondMax; } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 4 using namespace std; 5 6 void secondMax(vector<int> &arr) 7 { 8 int size = arr.size(); 9 if (size == 0 || arr.empty()) 10 return; 11 int max = INT_MIN; 12 int secondMax = INT_MIN; 13 for (int i = 0; i < size; ++i) 14 { 15 if (arr[i] > max) 16 { 17 secondMax = max; 18 max = arr[i]; 19 } 20 else { 21 if (arr[i] > secondMax) 22 secondMax = arr[i]; 23 } 24 } 25 cout << "max is " << max << endl; 26 cout << "second max is " << secondMax << endl; 27 } 28 29 int main() 30 { 31 vector<int> arr{ 6,4,1,3,2,5,7 }; 32 secondMax(arr); 33 34 return 0; 35 }
42、输出数组中只出现一次的数
Java实现:
package com.mian.demo; import java.util.HashMap; public class OnlyAppearOnceNum { public static void main(String[] args) { OnlyAppearOnceNum an=new OnlyAppearOnceNum(); int[] arr={ 6,4,1,3,2,5,7,2,1,4 }; an.onlyAppearOnceNum(arr); } private void onlyAppearOnceNum(int[] arr){ int size=arr.length; if(arr==null||size==0){ return; } HashMap<Integer,Integer> map=new HashMap<>(); for(int i=0;i<size;++i){ if(map.containsKey(arr[i])){ map.put(arr[i],map.get(arr[i])+1); }else{ map.put(arr[i],1); } } for(int i=0;i<size;++i){ if(map.get(arr[i])==1){ System.out.print(arr[i]+" "); } } } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 #include<unordered_map> 4 5 using namespace std; 6 7 void onlyAppearOnceNum(vector<int> &arr) 8 { 9 int size = arr.size(); 10 if (arr.empty() || size == 0) 11 return; 12 unordered_map<int, int> m; 13 for (int i = 0; i < size; ++i) 14 { 15 auto it = m.find(arr[i]); 16 if (it != m.end()) 17 ++it->second; 18 else 19 m[arr[i]] = 1; 20 } 21 for (int i = 0; i < size; ++i) 22 if (m[arr[i]] == 1) 23 cout << arr[i] << " "; 24 cout << endl; 25 } 26 27 int main() 28 { 29 vector<int> arr{ 6,4,1,3,2,5,7,2,1,4 }; 30 onlyAppearOnceNum(arr); 31 32 return 0; 33 }
43、等概率产生0和1
有一个随机数发生器,能以概率p生成0,以概率1-p生成1,问如何做一个随机数发生器使得生成0和1的概率相等。
分析:产生0的概率为p,产生1的概率为(1-p,产生01的概率为P(1-P),产生10的概率为(1-P)P,两者相等。
则新函数,产生01返回0,产生10返回1。
1 int random_0_1() 2 { 3 int i = rand(); 4 int j = rand(); 5 int res; 6 while (true) 7 { 8 if (i == 0 && j == 1) 9 { 10 res = 0; 11 break; 12 } 13 else if (i == 1 && j == 0) 14 { 15 res = 1; 16 break; 17 } 18 } 19 return res; 20 }
44、读文件,从文件中找到第一个重复的字符(考察文件读写,编程功底以及对异常的考虑)
Java实现:
package com.mian.algorithm; import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class ReadWriteFile { public static void main(String[] args)throws IOException{ ReadWriteFile rwf=new ReadWriteFile(); rwf.readWriteFile("D:/lina/in.txt","D:/lina/out.txt"); } private void readWriteFile(String in,String out){ File inFile=null; BufferedReader br=null; List<Integer> nums=new ArrayList<>(); try{ inFile=new File(in); if(!inFile.exists()||inFile.isDirectory()){ System.out.println("读入文件不存在!!!"); } br=new BufferedReader(new FileReader(inFile)); String tmp=br.readLine(); while(tmp!=null){ nums.add(Integer.parseInt(tmp)); System.out.print(tmp+"\t"); tmp=br.readLine(); } }catch (IOException e){ e.printStackTrace(); }finally { try { br.close(); }catch (IOException e){ e.printStackTrace(); } } Collections.sort(nums,(a,b)->a.compareTo(b)); BufferedWriter bw = null; try { File file = new File(out); if (!file.exists()) { file.createNewFile(); } FileWriter fw = new FileWriter(file.getAbsoluteFile()); bw = new BufferedWriter(fw); for(int i=0;i<nums.size();++i){ bw.write(nums.get(i).toString()); } } catch (IOException e) { e.printStackTrace(); }finally { try { bw.close(); }catch (IOException e){ e.printStackTrace(); } } } }
C++实现:
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 #include<fstream> 5 6 using namespace std; 7 8 void firstRepeateChar(string &str) 9 { 10 int size = str.size(); 11 if (str.empty() || size == 0) 12 return; 13 vector<int> help(256, 0); 14 for (int i = 0; i < size; ++i) 15 { 16 ++help[(int)str[i]]; 17 if (help[str[i]] == 2) 18 { 19 cout << str[i] << endl; 20 break; 21 } 22 } 23 } 24 25 void readFile(string &file) 26 { 27 ifstream infile; 28 infile.open(file); 29 if (!infile.is_open()) 30 { 31 cout << "Error opening file"; 32 exit(1); 33 } 34 string res; 35 string str; 36 while (infile>>str) 37 res += str; 38 infile.close(); 39 firstRepeateChar(res); 40 } 41 42 int main() 43 { 44 string name = "str.txt"; 45 readFile(name); 46 47 return 0; 48 }
45、符号匹配问题,考虑优先级
1 bool signMatch(string &str) 2 { 3 int size = str.size(); 4 if (str.empty() || size == 0) 5 return true; 6 stack<char> stk; 7 for (int i = 0; i < size; ++i) 8 { 9 char cur = str[i]; 10 if (cur == '{' || cur == '[' || cur == '(') 11 { 12 if (!stk.empty()) 13 { 14 char top = stk.top(); 15 if ((cur == '{'&&top == '{') || (cur == '{'&&top == '[') || (cur == '{'&&top == '(') || 16 (cur == '['&&top == '[') ||( cur == '['&&top == '(' )|| (cur == '('&&top == '(')) 17 return false; 18 else 19 stk.push(cur); 20 } 21 else 22 stk.push(cur); 23 } 24 else if (cur == '}' || cur == ']' || cur == ')') 25 { 26 if (!stk.empty()) 27 { 28 char top = stk.top(); 29 stk.pop(); 30 if ((cur == '}'&&top != '{') || (cur == ']'&&top != '[' )||( cur == ')'&&top != '(')) 31 return false; 32 } 33 else 34 return false; 35 } 36 } 37 if (!stk.empty()) 38 return false; 39 else 40 return true; 41 }
46、给定一个n个元素的数组,是否存在a,b,c三个元素,使用得a+b+c=0,找出所有符合这个条件的三元组。
分析:可以在 2sum问题的基础上来解决3sum问题,假设3sum问题的目标是target。每次从数组中选出一个数k,从剩下的数中求目标等于target-k的2sum问题。这里需要注意的是有个小的trick:当我们从数组中选出第i数时,只需要求数值中从第i+1个到最后一个范围内字数组的2sum问题。以选第一个和第二个举例,假设数组为A[],总共有n个元素A1,A2….An。很显然,当选出A1时,在子数组[A2~An]中求目标位target-A1的2sum问题,要证明的是当选出A2时,只需要在子数组[A3~An]中计算目标位target-A2的2sum问题,而不是在子数组[A1,A3~An]中。
证明如下:假设在子数组[A1,A3~An]目标位target-A2的2sum问题中,存在A1 + m = target-A2(m为A3~An中的某个数),即A2 + m = target-A1,这刚好是“对于子数组[A3~An],目标为target-A1的2sum问题”的一个解。即相当于对满足3sum的三个数A1+A2+m = target重复计算了。因此为了避免重复计算,在子数组[A1,A3~An]中,可以把A1去掉,再来计算目标是target-A2的2sum问题。对于本题要求的求最接近解,只需要保存当前解以及当前解和目标的距离,如果新的解更接近,则更新解。算法复杂度为O(n^2)。
Java实现:
package com.mian.demo; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ThreeSum { public static void main(String[] args) { ThreeSum ts=new ThreeSum(); int[] arr={ -1, 0, 1, 2, -1, -4 }; int target=0; List<List<Integer>> res=ts.threeSum(arr,target); for(int i=0;i<res.size();++i){ for(int j=0;j<res.get(i).size();++j){ System.out.print(res.get(i).get(j)+" "); } System.out.println(); } } private List<List<Integer>> threeSum(int[] arr, int target){ List<List<Integer>> res=new ArrayList<>(); List<Integer> tmp=null; int size=arr.length; if(arr==null||size<3){ return res; } Arrays.sort(arr); int i=0; while(i<size-2){ int j=i+1; int k=size-1; while(j<k){ if(arr[j]+arr[k]==target-arr[i]){ tmp=new ArrayList<Integer>(); tmp.add(arr[i]); tmp.add(arr[j]); tmp.add(arr[k]); res.add(tmp); --k; ++j; while(j<k&&arr[j]==arr[j-1]){ ++j; } while(j<k&&arr[k]==arr[k+1]){ --k; } }else if(arr[j]+arr[k]>target-arr[i]){ --k; while(j<k&&arr[k]==arr[k+1]){ --k; } }else{ ++j; while(j<k&&arr[j]==arr[j-1]){ ++j; } } } ++i; while(i<size-2&&arr[i]==arr[i-1]){ ++i; } } return res; } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 5 using namespace std; 6 7 vector<vector<int>> threeSum(vector<int> &nums, int target) 8 { 9 vector<vector<int>> res; 10 int size = nums.size(); 11 if (nums.empty() || size <3) 12 return res; 13 sort(nums.begin(), nums.end()); 14 int i = 0; 15 while (i < size - 2) 16 { 17 int j = i + 1; 18 int k = size - 1; 19 while (j < k) 20 { 21 if (nums[j] + nums[k] == target - nums[i]) 22 { 23 vector<int> tmp(3); 24 tmp[0] = nums[i]; 25 tmp[1] = nums[j]; 26 tmp[2] = nums[k]; 27 res.push_back(tmp); 28 tmp.clear(); 29 --k; 30 ++j; 31 while (j < k&&nums[j] == nums[j - 1]) 32 ++j; 33 while (j < k&&nums[k] == nums[k + 1]) 34 --k; 35 } 36 else if (nums[j] + nums[k] > target - nums[i]) 37 { 38 --k; 39 while (j < k&&nums[k] == nums[k + 1]) 40 --k; 41 } 42 else 43 { 44 ++j; 45 while (j < k&&nums[j] == nums[j - 1]) 46 ++j; 47 } 48 } 49 ++i; 50 while (i < size - 2 && nums[i] == nums[i - 1]) 51 ++i; 52 } 53 return res; 54 } 55 56 vector<vector<int>> threeSum2(vector<int>& nums) { 57 int size = nums.size(); 58 vector<vector<int>> res; 59 if (size<3) 60 return res; 61 sort(nums.begin(), nums.end()); 62 int target = 0; 63 for (unsigned int i = 0; i<size; ++i) 64 { 65 if (i>0 && nums[i] == nums[i - 1]) 66 continue; 67 int l = i + 1; 68 int r = size - 1; 69 while (l<r) 70 { 71 int s = nums[i] + nums[l] + nums[r]; 72 if (s>target) 73 --r; 74 else if (s<target) 75 ++l; 76 else 77 { 78 res.push_back(vector<int> {nums[i], nums[l], nums[r]}); 79 while (nums[l] == nums[l + 1]) 80 ++l; 81 while (nums[r] == nums[r - 1]) 82 --r; 83 ++l; 84 --r; 85 } 86 } 87 } 88 return res; 89 } 90 91 void printnumsay(vector<vector<int>> &nums) 92 { 93 for (int i = 0; i < nums.size(); ++i) 94 { 95 for (int j = 0; j < nums[i].size(); ++j) 96 cout << nums[i][j] << " "; 97 cout << endl; 98 } 99 } 100 101 int main() 102 { 103 vector<int> nums={ -1, 0, 1, 2, -1, -4 }; 104 vector<vector<int>> res = threeSum(nums,0); 105 vector<vector<int>> res2 = threeSum2(nums); 106 printnumsay(res); 107 printnumsay(res2); 108 109 return 0; 110 }
47、给定两颗二叉树,写一个函数判断这两棵树是否相等。
Java实现:
package com.mian.algorithm; import java.util.Scanner; public class IsSameTree { public static void main(String[] args) { IsSameTree isSameTree=new IsSameTree(); TreeNode root1=isSameTree.createTree(); TreeNode root2=isSameTree.createTree(); System.out.println(isSameTree.isSameTree(root1,root2)); } private boolean isSameTree(TreeNode head1,TreeNode head2){ if(head1==null&&head2==null){ return true; } if(head1==null||head2==null){ return false; } if(head1.val!=head2.val){ return false; } return isSameTree(head1.left,head2.left)&&isSameTree(head1.right,head2.right); } TreeNode createTree(){ TreeNode root; int data; Scanner sc=new Scanner(System.in); data=sc.nextInt(); if(data==100){ root=null; }else{ root=new TreeNode(data); root.left=createTree(); root.right=createTree(); } return root; } } class TreeNode{ public int val; TreeNode left; TreeNode right; TreeNode(){} TreeNode(int val){ this.val=val; this.left=null; this.right=null; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 class TreeNode 6 { 7 public: 8 int val; 9 TreeNode* left = nullptr; 10 TreeNode* right = nullptr; 11 TreeNode(){} 12 TreeNode(int x):val(x),left(nullptr),right(nullptr){} 13 }; 14 15 TreeNode* createTree() 16 { 17 TreeNode* root; 18 char data; 19 cin >> data; 20 if (data == '#') 21 root = nullptr; 22 else 23 { 24 root = new TreeNode(data); 25 root->left = createTree(); 26 root->right = createTree(); 27 } 28 return root; 29 } 30 31 bool isSameTree(TreeNode *head1, TreeNode *head2) 32 { 33 if (!head1&&!head2) 34 return true; 35 if (!head1 ||!head2) 36 return false; 37 if (head1->val != head2->val) 38 return false; 39 return isSameTree(head1->left, head2->left) && isSameTree(head1->right, head2->right); 40 } 41 42 int main() 43 { 44 TreeNode* root1=createTree(); 45 TreeNode* root2 = createTree(); 46 cout << isSameTree(root1, root2) << endl; 47 48 return 0; 49 }
48、不用+号做加法
Java实现:
package com.mian.algorithm; public class Add { public static void main(String[] args) { Add add=new Add(); int res=add.add(5,7); System.out.println(res); } private int add(int num1,int num2){ while(num2!=0){ int tmp=num1^num2; num2=(num1&num2)<<1; num1=tmp; } return num1; } }
C++实现:
1 #include<iostream> 2 3 using namespace std; 4 5 int add(int num1, int num2) 6 { 7 while (num2) 8 { 9 int tmp = num1^num2; 10 num2 = (num1&num2) << 1; 11 num1 = tmp; 12 } 13 return num1; 14 } 15 16 int main() 17 { 18 cout << add(5, 7) << endl; 19 20 return 0; 21 }
49、全排列
算法思路:
(1)n个元素的全排列=(n-1个元素的全排列)+(另一个元素作为前缀);
(2)出口:如果只有一个元素的全排列,则说明已经排完,则输出数组;
(3)不断将每个元素放作第一个元素,然后将这个元素作为前缀,并将其余元素继续全排列,等到出口,出口出去后还需要还原数组;
Java实现:
package com.mian.algorithm; public class ArrangeString { public static void main(String[] args) { ArrangeString arrangeString=new ArrangeString(); arrangeString.arrange("abc"); } private void arrange(String str){ char[] s=str.toCharArray(); int size=str.length(); if(size==0||str.isEmpty()){ return; } helper(s,0,size); } private void helper(char[] ch,int start,int size){ if(start==size-1){ for(int i=0;i<size;++i){ System.out.print(ch[i]+"\t"); } System.out.println(); }else{ for(int i=start;i<size;++i){ swap(ch,start,i); helper(ch,start+1,size); swap(ch,start,i); } } } private void swap(char[] ch,int i,int j){ char tmp=ch[i]; ch[i]=ch[j]; ch[j]=tmp; } }
C++实现:
1 #include<iostream> 2 #include<string> 3 4 using namespace std; 5 6 void swap(string &str, int i, int j) 7 { 8 char tmp = str[i]; 9 str[i] = str[j]; 10 str[j] = tmp; 11 } 12 13 void helper(string &str, int start, int size) 14 { 15 if (start == size - 1) 16 { 17 for (int i = 0; i < size; ++i) 18 cout << str[i] << " "; 19 cout << endl; 20 } 21 else 22 { 23 for (int i = start; i < size; ++i) 24 { 25 swap(str, start, i); 26 helper(str, start + 1, size); 27 swap(str, start, i); 28 } 29 } 30 } 31 32 void arrange(string &str) 33 { 34 int size = str.size(); 35 if (size == 0 || str.empty()) 36 return; 37 helper(str, 0, size); 38 } 39 40 int main() 41 { 42 string str = "abc"; 43 arrange(str); 44 45 return 0; 46 }
50、求一个序列的平衡点
序列的平衡点是指它左边的所有元素之和等于它右边的所有元素之和
Java实现:
package com.mian.algorithm; public class FindBalance { public static void main(String[] args) { FindBalance fb=new FindBalance(); int[] arr={5,1,-1,3,2,7,-3,0,4}; fb.findBalance(arr); } private void findBalance(int[] arr){ int size=arr.length; if(size==0||arr==null){ return; } int sum=0; int subSum=0; for(int i=0;i<size;++i){ sum+=arr[i]; } for(int i=0;i<size;++i){ if(subSum==(sum-subSum-arr[i])){ System.out.println("balance is "+arr[i]); }else{ subSum+=arr[i]; } } } }
C++实现:
1 #include<iostream> 2 #include<vector> 3 4 using namespace std; 5 6 void findBalance(vector<int> &arr) 7 { 8 int size = arr.size(); 9 if (size == 0 || arr.empty()) 10 return; 11 int sum = 0; 12 int subSum = 0; 13 for (int i = 0; i < size; ++i) 14 sum += arr[i]; 15 for (int i = 0; i < size; ++i) 16 if (subSum == sum - subSum - arr[i]) 17 cout << "balance is " << arr[i] << endl; 18 else 19 subSum += arr[i]; 20 } 21 22 int main() 23 { 24 vector<int> arr{5,1,-1,3,2,7,-3,0,4}; 25 findBalance(arr); 26 27 return 0; 28 }