allen.lipeng47
BAN USERpublic List<String> shuffleString(String str) {
List<String> ans = new ArrayList<>();
shuffleStringHelper(str, ans, new StringBuffer(), new boolean[str.length()]);
return ans;
}
private void shuffleStringHelper(String str, List<String> ans, StringBuffer curr, boolean[] visited) {
if (curr.length() >= str.length()) {
ans.add(curr.toString());
return;
}
for (int i = 0; i < visited.length; i++) {
if (visited[i] || curr.length() > 0 && curr.charAt(curr.length() - 1) == str.charAt(i)
|| i > 0 && str.charAt(i) == str.charAt(i - 1) && !visited[i - 1]) {
continue;
}
visited[i] = true;
curr.append(str.charAt(i));
shuffleStringHelper(str, ans, curr, visited);
curr.deleteCharAt(curr.length() - 1);
visited[i] = false;
}
}
position for alphabet: (ch - 'a') * 2
position for digit: (ch - '0') * 2 - 1
Can be solved by circle sort in O(n) time, O(1) space.
A straightforward way is to use TreeSet. Build a N elements treeset uses O(nlogn) time.
With treeset, we don't need even require the 2 streams are sorted. I'm guessing should be a much better way.
First solution, bitmap. Time complexity O(n), space complexity O(1).
Second solution, by bucket. Time complexity O(n), space complexity O(n).
Check my analysis: allenlipeng47.com/PersonalPage/index/view/199/nkey
Check my code on 2nd solution github: github.com/allenlipeng47/algorithm/blob/master/src/main/java/com/pli/project/algorithm/array/MaxGap.java
O(n) time, O(n) space complexity. Use double linked-list.
Analysis: allenlipeng47.com/PersonalPage/index/view/198/nkey
Check my code: github.com/allenlipeng47/algorithm/blob/master/src/main/java/com/pli/project/algorithm/array/MinConsecutiveSubStr.java
Check my analysis for this problem: allenlipeng47.com/PersonalPage/index/view/166/nkey
- allen.lipeng47 June 06, 2015@aleksey.klishin. what do you mean? DEEDBA, AB are not pair of palindrome. I doubt it is a counter example to @DR A.D.M's solution?
- allen.lipeng47 May 29, 2015check my explanation and solution:
allenlipeng47.com/PersonalPage/index/view/164/nkey
I think the code in the top is the most optimized one. But you gave out a good explanation to study this problem. Thanks dude!
- allen.lipeng47 May 28, 2015Considering the 2 edges are the option, your code works.
- allen.lipeng47 February 03, 2015Agree. Nice solution!
- allen.lipeng47 February 02, 2015Another solution is we use index i to iterate arr from beginning to end. Difference is that we should try to compare arr[i] and arr[i+1]. If arr[i]<arr[i+1], then i should jump 2 to forward.
In this way, iteration could be done faster.
My solution is between O(n) and O(logn). Check my website for detail: allenlipeng47.com/PersonalPage/index/view/128/nkey
1. Every time, check the middle element. If middle element is both smaller than left and right element, return middle.
2. Or if left of middle element is both smaller than left and middle element, there must be a local min in left part. Go left part.
3. Or if right of middle element is both smaller than right and middle element, there must be a local min in right part. Go right part.
4. Despite the above 3 cases, we should both check left and right part.
package feb;
public class LocalMin {
public static void main(String[] args) {
int[] arr = { 11, 5, 12, 7, 4, 0, 6 };
int result = localMin(arr);
System.out.println(result);
}
public static int localMin(int[] arr) {
return localMinUtil(arr, 0, arr.length - 1);
}
/*
* Return local minimum in arr[left,...,right]
*/
private static int localMinUtil(int[] arr, int left, int right) {
if (right - left < 2) {
return -1;
}
int mid = (left + right) >> 1;
if (arr[mid] < arr[mid - 1] && arr[mid] < arr[mid + 1]) {
return mid;
}
if (arr[mid - 1] < arr[mid] && arr[mid - 1] < arr[left]) {
// There must be localMin in arr[left,...,mid]
return localMinUtil(arr, left, mid);
}
if (arr[mid + 1] < arr[mid] && arr[mid + 1] < arr[right]) {
// There must be localMin in arr[mid,...,right]
return localMinUtil(arr, mid, right);
}
int result = localMinUtil(arr, left, mid);
if (result != -1) {
return result;
}
return localMinUtil(arr, mid, right);
}
}
It doesn't work for { 1, 3, 2, 4, 5, 7, 8, 9 }
- allen.lipeng47 February 02, 2015Hi Anselmo,
Can you fix the code? I ran the code. I don't think either your code or pavelkushtia's code for { 25, 33, 26, 58, 41, 59, 4 } is correct.
Assume the input from [0,W0], [1,W1],...[n,Wn], the selected index is i. Let totalWeight=sum(W0,...,Wn).
Now consider a new input [n+1,Wn+1], the probability to keep index I is totalWeight / (totalWeight + Wn+1), and probbability to have a new index n+1 is Wn+1 / (totalWeight + Wn+1).
See my analysis and code: allenlipeng47.com/PersonalPage/index/view/127/nkey
package feb;
public class ReturnWithProbabilityProportionalToItsWeight {
public static void main(String[] args) {
int[][] input = { { 1, 4 }, { 2, 2 }, { 3, 2 }, { 0, 0 } };
int result = getRandom(input);
System.out.println(result);
/*
* Following runs for 1000 times to check the answer correctness.
*
* int[] test = new int[3]; for (int i = 0; i < 1000; i++) {
* test[getRandom(input)]++; } for (int i = 0; i < test.length; i++) {
* System.out.print(test[i] + "\t"); }
*/
}
public static int getRandom(int[][] input) {
double totalWeight = input[0][1];
int result = 0;
for (int i = 1; i < input.length; i++) {
if (input[i][0] == 0 && input[i][1] == 0) {
break;
}
double newTotalWeight = totalWeight + input[i][1];
double newChance = ((double) input[i][1]) / newTotalWeight;
if (Math.random() <= newChance) {
result = i;
}
totalWeight = newTotalWeight;
}
return result;
}
}
To pavelkushtia,
This is not a correct solution!
What Anselmo said about "It is based on the observation that the element that holds the max QAZ is a local minimum of the array" is not correct.
For example, for array = { 25, 33, 26, 58, 41, 59, 4 }. The minimum of array is 4. the QAZ of 4 is 0. Obviously, the QAZ of this array is from 25, which is 5.
You should try this test case in your code and see the result.
As many people discussed, a O(nlogn) solution can be achieved by merge sort. Please check my analysis and solution: allenlipeng47.com/PersonalPage/index/view/126/nkey
package feb;
public class QAZ {
public static void main(String[] args) {
int[] arr = { 7, 8, 2, 3, 4, 5 };
int qaz = qaz(arr);
System.out.println(qaz);
}
public static int qaz(int[] arr) {
int[] eleTimes = new int[arr.length];
int[] helperQaz = new int[arr.length];
int[] helperTimes = new int[arr.length];
return qazUtil(arr, eleTimes, 0, arr.length - 1, helperQaz, helperTimes);
}
public static int qazUtil(int[] arr, int[] eleTimes, int start, int end,
int[] helperQaz, int[] helperTimes) {
if (start > end) {
return 0;
}
if (start == end) {
return 0;
}
int mid = start + (end - start) / 2;
int qazLeft = qazUtil(arr, eleTimes, start, mid, helperQaz, helperTimes);
int qazRight = qazUtil(arr, eleTimes, mid + 1, end, helperQaz,
helperTimes);
// 1. Update eleTimes in left part.
int pointerL = mid, pointerR = end;
int added = 0;
while (pointerL >= start) {
while (arr[pointerL] < arr[pointerR] && pointerR >= mid + 1) {
pointerR--;
added++;
}
eleTimes[pointerL] += added;
qazLeft = (eleTimes[pointerL] > qazLeft) ? eleTimes[pointerL]
: qazLeft;
pointerL--;
}
// 2. Mergesort left and right part into helperQaz, helperTimes
pointerL = start;
pointerR = mid + 1;
int helpIndex = start;
while (pointerL <= mid && pointerR <= end) {
if (arr[pointerL] < arr[pointerR]) {
helperQaz[helpIndex] = arr[pointerL];
helperTimes[helpIndex] = eleTimes[pointerL];
pointerL++;
} else {
helperQaz[helpIndex] = arr[pointerR];
helperTimes[helpIndex] = eleTimes[pointerR];
pointerR++;
}
helpIndex++;
}
while (pointerL <= mid) {
helperQaz[helpIndex] = arr[pointerL];
helperTimes[helpIndex] = eleTimes[pointerL];
pointerL++;
helpIndex++;
}
while (pointerR <= end) {
helperQaz[helpIndex] = arr[pointerR];
helperTimes[helpIndex] = eleTimes[pointerR];
pointerR++;
helpIndex++;
}
// 2.2 Copy result from helperQaz, helperTimes back to arr, eleTimes
for (int i = start; i <= end; i++) {
arr[i] = helperQaz[i];
eleTimes[i] = helperTimes[i];
}
return Math.max(qazLeft, qazRight);
}
}
If input is {4, 33 , 25 , 26 , 58 , 41 , 59 }, your code returns 4. Right answer should be 6.
- allen.lipeng47 February 01, 2015This is a topological sorting problem. Use the vector<String> to build the graph. Then do topological sorting on it. Below is my code. For more information, please visit my website: allenlipeng47.com/PersonalPage/index/view/105/nkey
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
public class TopogicalSorintDFS {
public static void main(String[] args) {
Vector<String> airports = new Vector<String>();
airports.add("JFK");
airports.add("LAX");
airports.add("SNA");
airports.add("RKJ");
airports.add("LAX");
airports.add("SNA");
Vector<String> result = findPath(airports);
System.out.println(result.toString());
}
public static Vector<String> findPath(Vector<String> airports) {
Map<String, AirNode> nodes = new HashMap<String, AirNode>();
// construct graph
for (int i = 0; i < airports.size(); i += 2) {
String from = airports.get(i);
String to = airports.get(i + 1);
if (!nodes.containsKey(from)) {
nodes.put(from, new AirNode(from));
}
if (!nodes.containsKey(to)) {
nodes.put(to, new AirNode(to));
}
nodes.get(from).outgoing.add(nodes.get(to));
}
Vector<String> result = new Vector<String>();
HashSet<String> visited = new HashSet<String>();
//start the dfs on graph
for (AirNode node : nodes.values()) {
dfs(node, visited, result);
}
return result;
}
public static void dfs(AirNode node, HashSet<String> visited,
Vector<String> result) {
if (visited.contains(node.airport)) {
return;
}
visited.add(node.airport);
for (AirNode curr : node.outgoing) {
dfs(curr, visited, result);
}
result.insertElementAt(node.airport, 0);
}
}
class AirNode {
String airport;
Set<AirNode> outgoing;
public AirNode(String airport) {
this.airport = airport;
outgoing = new HashSet<AirNode>();
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (obj instanceof AirNode) {
AirNode node = (AirNode) obj;
return this.airport.equals(node.airport);
}
return false;
}
public int hashCode() {
return this.airport.hashCode();
}
}
Check my analysis and O(logn) solution here:
allenlipeng47.com/PersonalPage/index/view/94/nkey
This is a wave print problem. For each even number i, make sure that num[i-1]<num[i]<num[i+1]
- allen.lipeng47 January 04, 2015The basic idea is to start from top line, and right line. For each start point (i,j), continuously print the (i+1,j-1).
My code:
import java.awt.Point;
public class DiagonalPrintMatrix {
public static void main(String[] args){
int[][] matrix = {
{1,2,3},
{4,5,6},
{7,8,9}
};
printMatrix(matrix);
}
public static void printMatrix(int[][] matrix){
for(int i=0;i<matrix.length;i++){
//start from top line
Point p = new Point(0, i);
while(p!=null){
p = printMatrix(matrix, p);
}
System.out.println();
}
for(int i=1;i<matrix.length;i++){
//start from the right line
Point p = new Point(i, matrix.length-1);
while(p!=null){
p = printMatrix(matrix, p);
}
System.out.println();
}
}
public static Point printMatrix(int[][] matrix, Point p){
System.out.print(matrix[p.x][p.y]+" ");
if(p.x+1>matrix.length-1||p.y-1<0){
return null;
}
return new Point(p.x+1, p.y-1);
}
}
LinkedList and hashmap. Use LinkedList for the LRU data structure. Use hashmap to locate the LinkedList element in O(1) time.
- allen.lipeng47 January 04, 2015Recursively iterate all possible () and +-*/ group.
- allen.lipeng47 December 31, 2014sliding window problem
- allen.lipeng47 December 31, 2014check my analysis and O(n) solution here: allenlipeng47.com/PersonalPage/index/view/98/nkey
- allen.lipeng47 December 31, 2014For O(n) solution, it is similar to max value in sliding window of array.
- allen.lipeng47 December 31, 2014Basic idea:
use DFS. use another array, the initial values of it is 1. For an element array[i][j], if the value is larger than 1, then continue to check another element. Or recursively DFS to its adjacency, which the adjacency has its next number. The DFS will return the longest steps the adjacency can reach. So, the value of array[i][j] is DFS result plus 1.
time O(n^2), space O(n^2)
This method is correct.
For the step1 and step2, do you mean going through B only for 1 time, you finish the both finding pivot and partitioning the array? If so, how do you do this? Can you provide the code? Thanks!
a=[0,…,a_start, …, a_mid,…,a_end,…,a.length-1]
b=[0,…,b_start, …, b_mid,…,b_end,…,b.length-1]
Element number of a[a_start,…,a_mid] and b[b_start,…,b_mid] is half_length.
find the kth from a and b.
Assume a_mid is larger than b_mid.
If k>=half_length, then we know that kth number can’t be in lower part of b, b[b_start,…,b_mid]. So next, we search a[a_start, a_end] and b[b_mid+1,…,b_end]. Meanwhile, we should set new value to k. k=k-(b_mid-b_start+1)
Return result:
if(a_start>a_end){
return b[b_start+k-1];
}
if(b_start>b_end){
return a[a_start+k-1];
}
To find my code and read more analysis, please visit my website: allenlipeng47.com/PersonalPage/index/view/94/nkey
What is the difference between using DFS recursion and the dynamic programming you mentioned? They are the same.
- allen.lipeng47 December 24, 2014Assume the test the array[], and we have a i loop from 0 to array.length-1.
My solution is to maintain an next_negative, which indicate the next negative element in the unsorted array, and next_positive, which indicate the next positive element in the unsorted array.
The both next_negative and next_positive only traverse the array one time.
Each time, test if the current i element is in right position or not. If it is right, check the next one.
If it is not in right position, we do following:
If the current position should be a negative, let next_negative traverse from its own position until it reach the first negative element in unsorted array. If next_negative is less than i, let next_negative be i+1.
If the current position should be a positive, let next_positve traverse from its own position until it reach the first positive element in un sorted array. If next_positive is less than i, let next_positive be i+1.
Now we have found the right position that we should put into the position array[i]. The critical matter here, is that we shouldnt simply do switch(a[i], a[next_negative]) or switch(a[i], a[next_positive]), because this would lose the original sort. Instead, we should do rotate.
For example, -1 (-2) -3 -4 (1) 2 3 4 5 6 7 8
We found the -2 is not in right position. After we traverse the next_positive, we found 1 should be there, since 1 is the first positive number in the unsorted array. So we should do rotate like this:
-1 (1 -2 -3 -4) 2 3 4 5 6 7 8
Then, it would be like this:
-1 1 (-2) -3 -4 2 3 4 5 6 7 8
-1 1 -2 (-3) -4 2 3 4 5 6 7 8
-1 1 -2 (-3) -4 (2) 3 4 5 6 7 8
-1 1 -2 (2 -3 -4) 3 4 5 6 7 8
Here, we can see we did the rotate, which helps to maintain the original sort.
Ok, now, I want to say, it won't be solved in O(n) time by this.
But we want an O(n) time, my answer is that if the array is given by form of linkedList, it can be solved in O(n) time.
Can't agree it is a O(n) solution. You have a while loop inside of for loop.
- allen.lipeng47 December 24, 20140ode, can you explain which 3 walls are removed? How do you store it?
- allen.lipeng47 December 23, 2014actually, for (c, 7, 8), (c, 7) and (c, 8) are sorted
- allen.lipeng47 December 23, 2014Another greedy algorithm takes O(n^2) time, but it can only provides a merely correct answer.
Assume the digits are stored in array num[].
for(int i=0; i<num.length(), k>0; i++, k--){
1. each time, find the rightmost largest digit among num[i+1,...,length-1]. Let's say it is it is num[large_pos].
2. if num[large_pos] equals num[i], then i++. until found a i, where num[i]<num[large_pos].
3. swap(num[i], num[large_pos])
}
An example is 1289349999, k is 4
1289349999
^ ^
9289349991
^ ^
9989349921
^ ^
9999349821
^ ^
9999349821
^ ^
9999943821
^
Each time, it gives a best solution from current to next step. But it doesn't guarantee a global best solution.
Correct answer, but it takes O(n^k) time.
- allen.lipeng47 December 22, 2014After reading the solutions, I summarize my solution:
Let's say the string is str.
1. find the latest b, let's say the position is i.
2. We should find j, where j is larger than i, and smaller than length of string. j is somewhere in str[i+1,...,length-1].
The essence of finding j, is to find the longest 'a' group. Among those group, do reverse and compare, find the smallest reverse.
For example,
aabaabab, the length of longest group is 2, the candidate is str[2,...,4].
aabaabaababaa, the length longest groups is 2, the candidates are str[2,...,4], str[2,...,5], str[2,...,12].
aabaaabaabaaa, the length of longest group is 3, the candidates are str[2,...,5], str[2,...12]
As for the time complexity, I would say, it is not O(n), but O(n^2). Because we should consider the complexity of the comparison for the reverse. It takes O(n) time comparision. And traversal j from i+1 to length-1 takes another O(n).
The space is O(1), because it only saves the best result, which we can find some way to store it as a integer number.
Use a global int[] to restore the state. And use recursion to traverse them. It is quite similar as 8 queens game.
- allen.lipeng47 December 21, 2014In the structure of my PatriciaTree, it has following parameters:
char c, indicate the char the node has.
HashMap<Character, PatriciaTree> children, indicate the children the node has.
String leftString, this a bit difficult to explain. So let me raise an example. If root only has a word "dog". So the structure would be like:
.root.......
..\.........
...d(og)....
But not:
.root.......
..\.........
...d........
....\.......
.....o......
......\.....
.......g....
So, in this case, I use the leftString to store the string after 'd', which is 'og'. And I call the node d(og) string leaf. Because it is a leaf, and it needs to indicate what string it still has.
I define 4 types of nodes in patricia tree:
STATE_ROOT, the root the patricia tree.
STATE_STRINGLEAF, it is a leaf, and it has left string in it. Like the example I showed above.
STATE_LEAF, it is a leaf, and it doesn't has left string.
For example, the 'g' and 't' nodes are both LEAF node, but not string leaf node.
.root.........
..\...........
...d..........
....\.........
.....o........
..../.\.......
...g...t......
STATE_MIDDLE, in the above case, the 'd' and 'o' are middle nodes.
In the following code. I demonstrate how to build a patricia tree, and the method to find if a word exists in a patricia tree.
import java.util.HashMap;
public class PatriciaTree {
public static final int STATE_ROOT = 0;
public static final int STATE_LEAF = 1;
public static final int STATE_STRINGLEAF = 2;
public static final int STATE_MIDDLE = 3;
char c;
HashMap<Character, PatriciaTree> children;
int state; //0 is root, 1 is leaf, 2 is leaf with string, 3 is middle
String leftString; //if the node is leaf with string, it has a rest word
PatriciaTree parent;
//store word into this PatriciaTree, word starts from pos
public boolean addNode(String word, int pos, PatriciaTree parent){
if(word==null||pos>=word.length()){
return false;
}
PatriciaTree child;
if(state==STATE_ROOT||state==STATE_MIDDLE){
//if it is root, then find if it children have tree with character pos[0]
child = children.get(word.charAt(pos));
if(child==null){ //it doesn't has word.charAt[pos], then create tree under it.
child = new PatriciaTree(word, pos, this);
children.put(word.charAt(pos), child);
return true;
}
return child.addNode(word, pos+1, this); //it has char, then create tree under its child.
}
if(state==STATE_LEAF){
//now it is leaf, and there are still chars, then just change it to a STRINGLEAF
this.state = STATE_STRINGLEAF;
this.leftString = word.substring(pos, word.length()-1);
return true;
}
if(state==STATE_STRINGLEAF){
if(word.charAt(pos)!=leftString.charAt(0)){
//1st char of leftString doesn't match word[pos], so create the tree under it.
//And create leftString as its subtree.
child = new PatriciaTree(word, pos, this);
children.put(word.charAt(pos), child);
child = new PatriciaTree(leftString, 0, this);
children.put(leftString.charAt(0), child);
this.state = STATE_MIDDLE;
return true;
}
//1st char of leftString match word[pos], so break the stringleaf into middle,
//and create its child with char of the 1st leftString
this.state = STATE_MIDDLE;
child = new PatriciaTree(leftString, 0, this);
children.put(leftString.charAt(0), child);
this.leftString = "";
child.addNode(word, pos+1, child);
return true;
}
return false;
}
public boolean findString(String word, int pos){
if(pos>=word.length()){
if(this.state==STATE_MIDDLE){
return false; //is in the middle, is not counted as found.
}
if(this.state==STATE_LEAF){
return true; //return true if this is leaf
}
return false;
}
PatriciaTree child;
if(this.state==STATE_ROOT||this.state==STATE_MIDDLE){
child = this.children.get(word.charAt(pos));
return child==null?false:child.findString(word, pos+1);
}
if(this.state==STATE_LEAF){
return false; //the word is larger than the leaf string
}
if(this.state==STATE_STRINGLEAF){
String strInWord = word.substring(pos, word.length());
if(leftString.equals(strInWord)){
return true;
}
}
return false;
}
public PatriciaTree(){
this.children = new HashMap<Character, PatriciaTree>();
}
public PatriciaTree(String word, int pos, PatriciaTree parent){
this.c = word.charAt(pos);
this.parent = parent;
this.state = STATE_LEAF;
this.children = new HashMap<Character, PatriciaTree>();
if(pos<word.length()-1){
this.state = STATE_STRINGLEAF;
this.leftString = word.substring(pos+1, word.length());
}
}
public static void main(String[] args) {
PatriciaTree root = new PatriciaTree();
root.state = STATE_ROOT;
String[] words = {"zebra", "zero", "dog", "dot", "ducks", "duh", "ducky"};
for(int i=0;i<words.length;i++){
root.addNode(words[i], 0, root);
}
System.out.println(root.findString("dogg", 0));
}
}
cheers!
- allen.lipeng47 December 21, 2014Hi 0xF4, could you please provide an counter-example?
- allen.lipeng47 December 21, 2014If we constraint the target number zero, this problem turns to find the median. I believe there is a certain way relating median.
- allen.lipeng47 December 21, 2014Thanks Source. You make sense! Well today, I found out this problem is a kinda complex DP problem. It requires a local[][] and global[][] to restore. Just like what simon.zhangsm showed.
Let me give the code I passed today:
public static int bestTimeToBuySellStockAtMostKTimes(int[] prices, int k){
if(prices==null || prices.length==0)
return 0;
int[] local = new int[prices.length];
int[] global = new int[prices.length];
for(int i=0;i<prices.length-1;i++)
{
int diff = prices[i+1]-prices[i];
for(int j=k;j>=1;j--)
{
local[j] = Math.max(global[j-1]+(diff>0?diff:0), local[j]+diff);
global[j] = Math.max(local[j],global[j]);
}
}
return global[k];
}
The key is to find all maximum increment subsequence. For example, the input is 4 3 2 5 4 6 7 1 7 8 5 6, the possible subsequence are [2 5] [4 6 7] [1 7 8] [5 6]. For these sub sequences, the profit are 3, 3, 7, 1. Find the top K profits from 3, 3, 7, 1. Use a K min heap to keep the results.
In this way, the time is O(N+logK), space is O(K)
Correct me if I'm wrong.
Check my analysis. The time complexity is O(G).
allenlipeng47.com/PersonalPage/index/view/89/nkey
At the beginning, I thought it is median problem too. This problem has weight, which is a weighted median problem. But median's weight is always 1.
In median problem, we find an x, which make sum|ai-x| is smallest. For example, in x-coordinate, a1 . a2 . . . . a3, we know the median is a2, since sum of distance from a2 to other 3 points is shortest.
But in this problem, each point ai has a weight wi, the problem is to find x, which sum(|ai-x|*wi) is smallest.
It does make sense. Thank you for the idea sharing!
- allen.lipeng47 December 20, 2014
RepA real dynamo when it comes to buying and selling carnival rides in Fort Lauderdale, FL. Spend several years working ...
RepKimRPierce, Employee at Achieve Internet
I am a customer service-oriented Travel Agent in Travel and Tourism industries. I strongly believe that the skills and abilities ...
RepDo you want to use Kamdev Vashikaran Mantra to subdue someone?Or If you are willing to attract your love ...
- allen.lipeng47 March 19, 2016